天天看點

java thread detach,C++文法學習筆記四十三:線程啟動、結束,建立線程多法、join,detach...

//

#include

#include

#include

#include

#include

using namespace std;

//自己建立的線程也要從一個函數(初始函數開始運作):

void myprint()

{

cout << "我的線程開始執行了" << endl;

cout << "我的線程開始執行了1" << endl;

cout << "我的線程開始執行了2" << endl;

cout << "我的線程開始執行了3" << endl;

cout << "我的線程開始執行了4" << endl;

cout << "我的線程開始執行了5" << endl;

cout << "我的線程開始執行了6" << endl;

cout << "我的線程開始執行了7" << endl;

//...

cout << "我的線程執行完畢了" << endl;

}

class TA{

public:

void operator()() //不能帶參數

{

cout << "我的線程operator()開始執行了" << endl;

cout << "我的線程operator()結束執行了" << endl;

}

};

class TA1{

public:

int &m_i;

TA1(int &i) : m_i(i){

cout << "TA()構造函數被執行" << endl;

}

TA1(const TA1 &ta) : m_i(ta.m_i){

cout << "TA()拷貝構造函數被執行" << endl;

}

~TA1(){

cout << "TA()析構函數被執行" << endl;

}

void operator()() //不能帶參數

{

cout << "m_i1的值為:" << m_i << endl;

cout << "m_i1的值為:" << m_i << endl;

cout << "m_i1的值為:" << m_i << endl;

cout << "m_i1的值為:" << m_i << endl;

}

};

int main()

{

//一:範例示範線程運作的開始和結束

//程式運作起來,生成一個程序,該程序所屬的主線程開始自動運作;

cout << "I Love China!" << endl; //實際上這個是主線程在執行,主線程從main()函數傳回,則整個程序執行完畢。

//主線程從main()開始執行,那麼我們自己建立的線程,也需要從一個函數開始運作(初始函數),一旦這個函數運作完畢,就代表着我們這個線程運作結束。

//整個程序是否執行完畢的标志是 主線程是否執行完,如果主線程執行完畢了,就代表整個程序執行完畢了;

//此時,一般情況下:如果其他子線程還沒有執行完畢,那麼這些子線程也會被作業系統強行終止。

//是以,一般情況下,我們得到一個結論:如果大家想保持子線程(自己用代碼建立的線程)的運作狀态的話,那麼大家要讓主線程一直保持運作,不要讓線程運作完畢。

//【這條規律有例外,後續會解釋這種例外,大家目前先這樣了解和記憶】

//a) 包含一個頭檔案thread要包含進來。

//b) 初始函數要寫。

//c) main中開始寫代碼。

//大家必須明确一點:有兩個線程在跑,相當于整個程式的執行有兩條線在同時走,是以,可以同時幹兩個事,

//即使一條線被堵住了,另外一條線還是可以通行的,這就是多線程;

//(1.1) thread: 是個标準庫裡的類

//(1.2) join(): 加入/彙合,說白了就是阻塞,阻塞主線程,讓主線程等待子線程執行完畢,然後子線程和主線程彙合。然後主線程再往下走

//如果主線程執行完畢了,但子線程沒執行完畢,這種程式員是不合格的,寫出來的程式也是不穩定的。

//一個書寫良好的程式,應該是主線程 等待子線程執行完畢後 自己才能最終退出;

//(1.3) detach():傳統多線程程式主線程要等待子線程執行完畢,然後自己再最後退出;

//detach :分離,也就是主線程不和子線程彙合了,你主線程執行你的,我子線程執行我的,你主線程也不必等

//我子線程運作結束, 你可以先執行結束。

//為什麼引入detach(): 我們建立了很多子線程,讓主線程逐個等待子線程結束,這種程式設計方法不太好,是以引入

//了detach();一旦detach()之後, 與這個主線程關聯的thread對象就會失去與這個主線程關聯,此時這個子線程

//就會駐留在背景運作(主線程跟該子線程失去聯系),這個子線程就相當于被C++運作時刻接管,當這個子線程

//指向完成後,由運作時庫負責清理該線程相關的資源(守護線程)。

//detach()使線程myprint失去我們自己的控制。

//(1.4) joinable() : 判斷是否可以成功使用join()或者detach()的;傳回true(可以join或者detach)或者false(不能join不能detach);

//myprint可調用對象

//thread mytobj(myprint); //建立了線程,線程執行起點(入口)myprint(), (2) myprint線程開始執行。

//

//if (mytobj.joinable()){

//cout << "1: joinable() == true" << endl;

//}

//else{

//cout << "1: joinable() == false" << endl;

//}

//阻塞主線程并等待myprint子線程執行完

//mytobj.join(); //主線程阻塞到這裡等待myprint()執行完,當子線程執行完畢,這個join()就執行完畢,主線程就繼續往下走。

//mytobj.detach(); //一旦調用了 detach(), 就不能再用join() 否則系統會報告異常。

//二:其他建立線程的手法

//(2.1)用類對象(可調用對象),以及一個問題範例

//大家可能還有一個疑問:一旦調用了detach(),那我主線程執行結束了,我這裡用的這個ta這個對象還在嗎?(對象不在了)

//這個對象實際上是被複制到線程中去;執行完主線程後,ta會被銷毀,但是所複制TA對象依舊存在。

//是以,隻要你這個TA類對象裡沒有引用,沒有指針,那麼就不會産生問題;

TA ta;

thread mytobj3(ta); // ta :可調用對象

mytobj3.join(); //等待子線程執行結束

int myi = 6;

TA1 ta1(myi);

thread mytobj4(ta1); // ta :可調用對象

mytobj4.join(); //等待子線程執行結束

mytobj4.detach();

//(2.2)用lambda表達式

auto mylamthread = [] {

cout << "我的線程3開始執行了" << endl;

cout << "我的線程3執行結束了" << endl;

};

thread mytobj5(mylamthread);

mytobj5.join();

mytobj5.detach();

cout << "I Love China 1!" << endl;

cout << "I Love China 2!" << endl;

cout << "I Love China 3!" << endl;

cout << "I Love China 4!" << endl;

cout << "I Love China 5!" << endl;

cout << "主線程收尾,最終主線程安全正常退出!" << endl;

system("pause");

}