Linux 下建立線程的函數是 pthread_create(),函數原型是:
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
參數說明:
thread:指向pthread_t類型(即指向線程)的指標,用於引用新建立的線程,實質為線程id。
attr:用於設定線程的屬性,一般不需要特殊的屬性,初級選手設定為NULL即可。
*(*start_routine)(void *):傳遞新線程所要執行的函數地址。
arg:新線程所要執行的函數的參數。
調用如果成功,則傳回值是0,如果失敗,如超過系統規定的最大線程數或記憶體不足,則返回錯誤碼。
前2個參數很簡單,主要所後面2個參數。
第三個參數為線程實際運行函數的地址,即需要傳一個函數指標過去,第四個則所該函數的參數,也是指標。
使用面向過程的多線程較為簡單,例子就不列舉了。可是將簡單的面向過程改為物件導向時,如將線程函數寫為類的成員函數時,編譯器總是報錯。類型轉換無效!!
開始時怎麼改變類型都是不行。後來未發現把之前可以用的函式宣告為類成員時,這是再建立線程時也不能用類。我才意識到可能與類有關。經查詢,類中的線程函數成員必須聲明為static,否則參數將不匹配。為什麼呢?
看第四個參數,類型為void *,而類成員函數即使你聲明為void * ,但是還有一個隱含參數this,所以編譯器報類型轉換無效了!!!!!
解決方案,要麼將線程函式宣告為static,要麼將線程函數寫在類外。使用線程函數的參數將對象傳遞進線程函數。
一個例子如下:
/*************************************1,Dog 類中有2個函數成員,shout 啟動線程,************************************/#include <iostream>#include <pthread.h>#include <stdlib.h>using namespace std;class Dog{ private: string name; int age; pthread_t pid;//對象成長線程標號 bool live; public: Dog(int n=1,string nm="Hali"); void shout(); pthread_t getPID(); friend void * growing(void * o);//dog growing thread friend void * dshout(void * o);//shout thread};/********成長線程,每2秒age加1直到age等於20*******/void * growing(void * o){ Dog *d=(Dog*)o; while(d->age < 21) { sleep(2); ++d->age; } d->live=false;//dead and quit}Dog::Dog(int n, string nm): age(n),name(nm){ pthread_t id; int res; res=pthread_create(&id,NULL,growing,this); if(res!=0) { cerr<<"Error!"<<endl; exit(1); } pid=id; live=true; cout<<"I'm a dog,my name is "<<name<<endl;}void* dshout(void *o){ Dog *d=(Dog*)o; while(d->live) { cout<<"My name is "<< d->name << ", I'm " <<d->age <<" now. "<< endl; sleep(3); }}void Dog::shout(){ pthread_t id; int res=pthread_create(&id,NULL,dshout,this); if(res!=0) { cerr<< "Error shout!" <<endl; exit(1); }}pthread_t Dog::getPID(){ return pid;}int main(){ Dog a,b(4,"Benjm"); a.shout(); b.shout(); while(1) { cout<<"\t\t\t Main Waiting ...."<<endl; sleep(5); } return 0;}
一個很簡單的例子,不過對於我這樣的新手弄類一天才弄好。