lpa編程
package demo;
/**
* 銀行
*/
public class Bank {
//存入賬戶,也就是共享數據,其實應更復雜,比如一家銀行有n個儲戶,或者一個用戶有n個銀行賬戶...
private Account account = new Account();
/**
* 這里安全,否則顯示賬戶余額可能出現問題
* @param mony
*/
public synchronized void putMony(int pid, int timeIndex, double money){
account.inMoney(money);
display(pid, timeIndex);
}
private void display(int pid, int timeIndex){
System.out.println("#pid:"+timeIndex+":"+account.getTotal());
}
public static void main(String[] args) {
Bank bank = new Bank();
Person person1 = new Person(bank, 1, 3, 3000);
Person person2 = new Person(bank, 2, 3, 3000);
person1.start();
person2.start();
}
}
/**
* 儲戶
*/
class Person extends Thread{
private Bank bank;//銀行
private int times;//交易次數
private double money;//每次交易金額
private int pid;//用戶ID
public Person(Bank bank, int pid, int times, double money) {
this.bank = bank;
this.pid = pid;
this.times = times;
this.money = money;
}
public void run() {
for(int i = 0; i < times; i++){
bank.putMony(pid, i, money);
}
}
}
/**
* 賬戶
*/
class Account {
//總額
private double total;
public Account() {
//開戶後,賬戶余額設為0
this.total = 0;
}
public double getTotal() {
return total;
}
/**
* 存錢
* @param money
*/
public void inMoney(double money) {
this.total += money;
}
/**
* 取錢(自行處理不能透支的情況...)
* @param money
*/
public void outMoney(double money) {
this.total -= money;
}
}
自己仔細分析下吧
㈡ c語言,編寫程序,通過指針操作,比較兩個有序數組中的元素,輸出兩個數組中第一個相同的元素值
c語言指針2個數組查詢比較代碼如下:
#include<stdio>
intmain()
{
int*lpa,*lpb;
inta[100],b[100],alen,blen,i,j;
printf("輸入數組a長度: ");
scanf("%d",&alen);
printf("輸入%d個有序數據給數組a ",alen);
for(i=0;i<alen;i++)scanf("%d",&a[i]);
printf("輸入數組b長度: ");
scanf("%d",&blen);
printf("輸入%d個有序數據給數組a ",alen);
for(i=0;i<alen;i++)scanf("%d",&a[i]);
//查詢比較
lpa=a;
for(i=0;i<alen;i++)
{
lpb=b;
for(j=0;j<blen;j++)
{
if(*lpb==*lpa)break;
lpb++;
}
if(*lpb==*lpa)break;
lpa++;
}
if(*lpb==*lpa)
{
printf("兩數組中發現第一個相同元素:%d",*lpa);
}
else
{
printf("兩數組中沒有發現相同元素");
}
}
㈢ 誰知道多線程編程
主要內容:
1, 工作者線程
2, 用戶界面線程
3, 同步
線程被分為工作者線程和用戶用戶界面線程。用戶界面的線程的特點是擁有單獨的消息隊列,可以具有自己的窗口界面,能夠對用戶輸入和事件作出反應。
可以用以下方法建立一個工作者線程。
UINT MyThreadProc(LPVOID pParam)
{
…
}
AfxBeginThread(MyThread,..);
它有六個參數,第一個為控制函數,第二個為啟動線程時傳給控制函數的入口參數,當前線程的優先順序,當前線程的棧的大小,當前線程的創建狀態,安全屬性,後四個有默認值。
用戶界面線程:
首先利用應用程序向導建立單文檔程序Thread,再建立Thread1 : public CWinThread,
Frame1 : public CFrameWnd,可以用Ctrl+w建立這兩個新類。
在CThreadApp中加一個指針Thread1* pThread1,在BOOL CThreadApp::InitInstance()
中進行初始化:
pThread1 = new Thread1();
pThread1->CreateThread();
將Thread1的構造函數改成公有。
在Thread1中加一個指針Frame1* m_pWnd,然後初始化。
BOOL Thread1::InitInstance()
{
m_pWnd = new Frame1();
return TRUE;
}
把Frame1的構造函數改成公有,在Thread.h中包含#include "Frame1.h"。
在資源編輯器中編輯一個菜單IDR_MENU,它有一個菜單項ID_BEGIN。
Frame1::Frame1()
{
Create(NULL,"Demo");
ShowWindow(SW_SHOW);
UpdateWindow();
CMenu menu;//可以用局部變數,因為以後不會用到它了,加菜單。
menu.LoadMenu(IDR_MENU);
SetMenu(&menu);
}
同步
多線程的一個難點是各線程間的協調。同樣的方法在CThreadApp中再開一個線程。
BOOL CThreadApp::InitInstance()
{
。。。。。。
pThread1 = new Thread1();
pThread1->CreateThread();
pThread2 = new Thread1();
pThread2->CreateThread();
。。。。。。
}
為IDR_MENU中的菜單在Frame1中設立響應函數,方法也是Ctrl+w打開類向導。並在Frame1中定義一個全局整形變數n,初始值為0.
HANDLE handle=CreateSemaphore(NULL,0,1,"he");
WaitForSingleObject(handle,10000);
CString str;
n++;
str.Format("第%d次工作",n);
MessageBox(str);
ReleaseSemaphore(handle,1,NULL);
當你點擊Frame1的菜單時,會彈出一個對話框,暫時不要點 確定,點擊另一個線程的菜單,暫不會彈出對話框,確定剛才的對話框,另一個線程的對話框也彈出來了。
這個同步的方法稱為信號量。它允許有限的線程存取某個共享的系統資源,採用計數器來實現信號量。
HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpa,LONG cSemInitial,LONG cSemMax,LPTSR lpszSemName);
第一個參數來指明所創建的對象是否可以被其子進程繼承。如果你希望在所有的子進程之間共享這個信號量,可以把它的成員bInheritHandle設為true,也可以直接設為NULL來使用默認的安全設置第二個參數是還可以讓幾個線程使用,第三個參數是最多可以讓幾個線程使用。
最後參數是信號量的名字,在其它的進程中調用CreateSemapphore()或OpenSemaphore()時使用這個字元串作為參數之一就可以得到信號量的句柄。
ReleaseSemaphore(HANDLE hSemaphore, LONG cRelease,LPLONG plPrev)
㈣ 基於遺傳演算法路徑優化C++編程
[cpp]
bool CAStar::Search(int X, int Y, std::list<POINT> &lResult, double dbGapBreak)
{
if(X < 0 || Y < 0
|| X > m_dwMapWidth || Y > m_dwMapWidth ||
m_dwDestinationX < 0 || m_dwDestinationX < 0 ||
m_dwDestinationX > m_dwMapWidth || m_dwDestinationY > m_dwMapHeight)
{
//_outf("坐標或地圖參數錯誤!");
return false;
}
LPAPOINT p = new APOINT;
p->x = X;
p->y = Y;
p->parent = NULL;
p->dbGap = _p2g(X, Y, m_dwDestinationX, m_dwDestinationY);
m_lOpen.push_front(p);//起始節點加入到開啟列表
m_lSafe.push_back(p);//加入到公共容器,任何新分配的節點,都要加入到這里,便於演算法執行完後清理
std::list<LPAPOINT>::iterator it;
DWORD dwTime = clock();
while(!m_lOpen.empty())
{
//這里就是反復遍歷開啟列表選擇距離最小的節點
it = GetMingapNode();
if((*it)->dbGap <= dbGapBreak)
break;
p = *it;
GenerateSuccessors(it);
}
if(!m_lOpen.empty())
{
//如果列表不為空,從最後一個節點開始拷貝路徑到返回值中
//_outf("最終尋路到:%X, %X", p->x, p->y);
POINT point;
while(p)
{
point.x = p->x;
point.y = p->y;
lResult.push_front(point);
p = p->parent;
}
}
for(it = m_lSafe.begin(); it != m_lSafe.end(); ++it)
{
//清理內存
if(*it != NULL)
{
m_pMap[(*it)->y][(*it)->x] = 1;//會被添加到m_lSafe的節點,一定是最初為1的節點,所以可以在這里恢復地圖數據
delete (*it);
*it = NULL;
}
}
m_lSafe.clear();//清空容器
//_outf("耗時:%d 毫秒", clock() - dwTime);
if(m_lOpen.empty())
{
//_outf("尋路失敗");
return false;
}
m_lOpen.clear();//清空開啟列表
//_outf("尋路成功,節點數:%d", lResult.size());
return true;
}
bool CAStar::Search(int X, int Y, std::list<POINT> &lResult, double dbGapBreak)
{
if(X < 0 || Y < 0
|| X > m_dwMapWidth || Y > m_dwMapWidth ||
m_dwDestinationX < 0 || m_dwDestinationX < 0 ||
m_dwDestinationX > m_dwMapWidth || m_dwDestinationY > m_dwMapHeight)
{
//_outf("坐標或地圖參數錯誤!");
return false;
}
LPAPOINT p = new APOINT;
p->x = X;
p->y = Y;
p->parent = NULL;
p->dbGap = _p2g(X, Y, m_dwDestinationX, m_dwDestinationY);
m_lOpen.push_front(p);//起始節點加入到開啟列表
m_lSafe.push_back(p);//加入到公共容器,任何新分配的節點,都要加入到這里,便於演算法執行完後清理
std::list<LPAPOINT>::iterator it;
DWORD dwTime = clock();
while(!m_lOpen.empty())
{
//這里就是反復遍歷開啟列表選擇距離最小的節點
it = GetMingapNode();
if((*it)->dbGap <= dbGapBreak)
break;
p = *it;
GenerateSuccessors(it);
}
if(!m_lOpen.empty())
{
//如果列表不為空,從最後一個節點開始拷貝路徑到返回值中
//_outf("最終尋路到:%X, %X", p->x, p->y);
POINT point;
while(p)
{
point.x = p->x;
point.y = p->y;
lResult.push_front(point);
p = p->parent;
}
}
for(it = m_lSafe.begin(); it != m_lSafe.end(); ++it)
{
//清理內存
if(*it != NULL)
{
m_pMap[(*it)->y][(*it)->x] = 1;//會被添加到m_lSafe的節點,一定是最初為1的節點,所以可以在這里恢復地圖數據
delete (*it);
*it = NULL;
}
}
m_lSafe.clear();//清空容器
//_outf("耗時:%d 毫秒", clock() - dwTime);
if(m_lOpen.empty())
{
//_outf("尋路失敗");
return false;
}
m_lOpen.clear();//清空開啟列表
//_outf("尋路成功,節點數:%d", lResult.size());
return true;
}
新增的SearchEx源代碼如下:
nBeginSift 參數為循環初始值,nEndSift為循環結束值,其實就是一個for循環的起始值與結束值。
這個循環的引用計數,最終會被 乘於 10 來作為距離分段選擇路徑進行路線優化
nBeginSift 與 nEndSift的間距越大,並不表示最終路徑就越好,最終優化出來的路徑,還是會和地形有關。
其實最好路徑優化演算法是按照角度的變化來選擇路徑優化,但是預計開銷會比較大,有了這個優化方式作為基礎,你可以自己去寫根據角度變化來優化的演算法。
[cpp]
bool CAStar::SearchEx(int X, int Y, std::list<POINT> &lResult, double dbGapBreak, int nBeginSift, int nEndSift)
{
DWORD dwTime = clock();
if(!Search(X, Y, lResult, dbGapBreak))
return false;
std::list<POINT>::iterator it = lResult.begin();
std::list<POINT>::iterator it2 = it;
std::list<POINT> l2;
for(int i = nBeginSift; i < nEndSift; i++)
{
it = lResult.begin();
it2 = it;
for(;it != lResult.end(); ++it)
{
if(_p2g(it2->x, it2->y, it->x, it->y) > (double)(i * 10))
{
SetDestinationPos(it->x, it->y);
l2.clear();
if(Search(it2->x, it2->y, l2, 0.0))
{
it = lResult.erase(it2, it);
lResult.insert(it, (l2.begin()), (l2.end()));
}
it2 = it;
}
}
}
_outf("耗時:%d 毫秒", clock() - dwTime);
return true;
}
bool CAStar::SearchEx(int X, int Y, std::list<POINT> &lResult, double dbGapBreak, int nBeginSift, int nEndSift)
{
DWORD dwTime = clock();
if(!Search(X, Y, lResult, dbGapBreak))
return false;
std::list<POINT>::iterator it = lResult.begin();
std::list<POINT>::iterator it2 = it;
std::list<POINT> l2;
for(int i = nBeginSift; i < nEndSift; i++)
{
it = lResult.begin();
it2 = it;
for(;it != lResult.end(); ++it)
{
if(_p2g(it2->x, it2->y, it->x, it->y) > (double)(i * 10))
{
SetDestinationPos(it->x, it->y);
l2.clear();
if(Search(it2->x, it2->y, l2, 0.0))
{
it = lResult.erase(it2, it);
lResult.insert(it, (l2.begin()), (l2.end()));
}
it2 = it;
}
}
}
_outf("耗時:%d 毫秒", clock() - dwTime);
return true;
}