先總結延申以下前面(一)所講的內容。
主線程從main()函數開始執行,我們創建的線程也需要一個函數作為入口開始執行,所以第一步先初始化函數。
整個進程是否執行完畢的標志是主線程是否執行完畢,一般情況下,如果想要保持子線程的運行狀態,那么要主線程保持運行。
本章從兩方面介紹創建線程的方法:
一、用函數創建線程:
關鍵詞:thread(類),join() ,detach(),joinable().
join(),阻塞主線程,等待子線程執行完畢后,才到主線程執行。
detach(),分離主線程,主線程和子線程各走各的,所以會出現多次運行會發現,運行結果可能不同,這時候需要考慮一個問題,主線程如果執行完了,子線程還沒跑完,這就可能出現一定問題了。
joinable(),判斷是否使用了join()或者detach(),是返回false,否返回true。
注意:join()和detach()不能同時使用,這兩個函數本來就有互斥的關系。
1 #include <iostream> 2 #include <thread> 3 void my_thread() 4 { 5 for (int i = 1; i <= 5; i++) 6 { 7 cout << "my_thread" << i << endl; 8 } 9 } 10 int main() 11 { 12 thread my_threadObj(my_thread); //創建一個子線程,並傳入子線程的函數入口my_thread 13 if (my_threadObj.joinable()) //返回true代表沒有使用join()或者detch() 14 { 15 my_threadObj.join(); //阻塞主線程,並讓主線程等待子線程執行完 16 } 17 else 18 { 19 return -1; 20 } 21 //my_threadObj.detach(); //分離主線程,子線程與主線程各自運行,所以每次運行結果可能不同 22 for (int i = 1; i <=5; i++) 23 { 24 cout << "main_thread" << i << endl; 25 } 26 return 0; 27 }
二、其他方法創建線程
1.用類對象
一旦用了detach()將子線程和主線程分離開,那么主線程執行完后,對象ca已經被銷毀,但實際上在子線程上的對象並不是ca,而是ca的拷貝對象,它並沒有被銷毀,還存在與子線程中。
1 class CA 2 { 3 public: 4 void operator()() 5 { 6 cout << "my_thread1" << endl; 7 cout << "my_thread2" << endl; 8 cout << "my_thread3" << endl; 9 cout << "my_thread4" << endl; 10 cout << "my_thread5" << endl; 11 } 12 CA() 13 { 14 cout << "調用構造函數" << endl; 15 } 16 CA(const CA&a) 17 { 18 cout << "調用拷貝構造函數" << endl; 19 } 20 ~CA() 21 { 22 cout << "調用析構函數" << endl; 23 } 24 }; 25 int main() 26 { 27 CA ca; 28 thread my_threadObj(ca); //創建一個子線程,可調用對象為ca 29 if (my_threadObj.joinable()) //返回true代表沒有使用join()或者detch() 30 { 31 my_threadObj.join(); //阻塞主線程,並讓主線程等待子線程執行完 32 } 33 for (int i = 1; i <= 5; i++) 34 { 35 cout << "main_thread" << i << endl; 36 } 37 return 0; 38 }
2.用lambda表達式
1 int main() 2 { 3 auto mylabda_thread = [] 4 { 5 for (int i = 1; i <= 5; i++) 6 { 7 cout << "mythread" << i << endl; 8 } 9 }; 10 thread mythreadObj(mylabda_thread); 11 mythreadObj.detach(); 12 for (int i = 1; i <= 5; i++) 13 { 14 cout << "main_thread" << i << endl; 15 } 16 return 0; 17 }