創建線程
子線程在創建時啟動。使用功能std::thread類創建線程對象。
線程關聯的可調對象可以是:普通函數、仿函數對象、Lambda表達式、非靜態成員函數、靜態成員函數。
示例
普通函數
1 #include <thread> 2 #include <iostream> 3 4 using namespace std; 5 6 void test() 7 { 8 cout << "子線程開始執行!" << endl; 9 //do something 10 cout << "子線程執行完畢!" << endl; 11 } 12 int main() 13 { 14 thread t(test); 15 t.join(); //主線程等待子線程 16 return 0; 17 }
仿函數對象
1 #include <thread> 2 #include <iostream> 3 4 using namespace std; 5 class Test{ 6 public: 7 void operator()(){ 8 cout << "子線程開始執行!" << endl; 9 //do something 10 cout << "子線程執行完畢!" << endl; 11 } 12 13 }; 14 int main() 15 { 16 // thread t(Test()); 這種寫法會編譯器會認為是一個函數聲明,這個函數帶有一個參數(函數指針指向沒有參數並返回Test對象的函數) 17 thread t((Test())); //可以使用加小括號,或者使用一只初始化,或者傳入命名變量 18 t.join(); //主線程等待子線程 19 return 0; 20 }
Lambda表達式
1 #include <thread> 2 #include <iostream> 3 4 using namespace std; 5 6 int main() 7 { 8 thread t( 9 [] () { 10 cout << "子線程開始執行!" << endl; 11 //do something 12 cout << "子線程執行完畢!" << endl; 13 } 14 ); 15 t.join(); //主線程等待子線程 16 return 0; 17 }
非靜態成員函數,靜態成員函數
以下的下寫法中是將對象拷貝了一份副本來創建線程。當我們在進行共享數據的管理時,有時候需要傳入對象的指針或者地址。而靜態成員函數,不需要傳入對象,只需要傳入類函數地址。根據C++對象模型,這很好理解因為編譯器對非靜態成員函數的處理需要this指針,而對靜態成員函數的處理不需要。【C++】對象模型之Function
1 #include <thread> 2 #include <iostream> 3 4 using namespace std; 5 class Test{ 6 public: 7 void test(){ 8 cout << "子線程開始執行!" << endl; 9 // do somesthing 10 cout << "子線程執行完畢!" << endl; 11 } 12 }; 13 14 int main() 15 { 16 Test obj; 17 thread t(&Test::test, obj); //注意寫法,傳入成員函數地址,還需要傳入對象 18 t.join(); //主線程等待子線程 19 return 0; 20 }
容器管理多個線程
我們可以使用容器來對多個線程進程管理,為自動化管理線程打下基礎。另外std::thread::hardware_concurrency()返回硬件支持並發的線程數量,這里的並發是指硬件可以並行執行多少個線程,而不是我們一般所說的時間片輪轉的那種並發。例如,多核系統中,返回值可以是CPU核芯的數量。
1 #include <iostream> 2 #include <thread> 3 #include <vector> 4 5 using namespace std; 6 7 void func(int i) 8 { 9 cout << "子線程func" << i << "開始執行!" << endl; 10 //do something 11 //方法二 12 cout << "func線程" << i << "的id: " << this_thread::get_id() << endl; 13 cout << "子線程func" << i << "執行結束!" << endl; 14 } 15 16 int main() 17 { 18 cout << "主線程main開始執行!" << endl; 19 cout << "main線程的id: " << this_thread::get_id() << endl; 20 vector<thread> thdvec; 21 int n; 22 cin >> n; 23 //運行時確定線程數量 24 for (int i = 0; i < n; ++i) 25 thdvec.push_back(thread(func, i)); 26 27 for (auto iter = thdvec.begin(); iter != thdvec.end(); ++iter) 28 iter->join(); 29 cout << "主線程main執行結束!" << endl; 30 return 0; 31 }
獲取線程id
線程標識類型是 std::thread::id 類型。有兩種獲取id的方法。
方法一:可以通過調用 std::thread 對象的成員函數 get_id() 來獲取id。
方法二:在當前線程中使用std::this_thread::get_id()來獲取線程id。
1 #include <thread> 2 #include <iostream> 3 4 using namespace std; 5 6 void func() 7 { 8 cout << "子線程func開始執行!" << endl; 9 //do something 10 //方法二 11 cout << "func線程的id: " << this_thread::get_id() << endl; 12 cout << "子線程func執行結束!" << endl; 13 } 14 15 int main() 16 { 17 18 cout << "主線程main開始執行!" << endl; 19 cout << "main線程的id: " << this_thread::get_id() << endl; 20 thread t(func); 21 //方法一 22 cout << "在main線程中獲取func線程id:" << t.get_id() << endl; 23 t.join(); 24 cout << "主線程main執行結束!" << endl; 25 return 0; 26 }