1、等待線程執行完成
join() 方法數會阻塞主線程直到目標線程調用完畢,即join會直接執行該子線程的函數體部分。
2、暫停線程(線程休眠)
使用std::this_thread::sleep_for或std::this_thread::sleep_until。
#include <thread> #include <iostream> #include <chrono> using namespace std::chrono; void pausable() { // sleep 500毫秒 std::this_thread::sleep_for(milliseconds(500)); // sleep 到指定時間點 std::this_thread::sleep_until(system_clock::now() + milliseconds(500)); } int main() { std::thread thread(pausable); thread.join(); return 0; }
3、線程終止
一般情況下當線程函數執行完成后,線程“自然”停止。但在std::thread中有一種情況會造成線程異常終止,那就是:析構。當std::thread實例析構時,如果線程還在運行,則線程會被強行終止掉,這可能會造成資源的泄漏,因此盡量在析構前join一下,以確保線程成功結束。
4、線程copy
std::thread a(foo);
std::thread b;
b = a;
將a的線程給了b,a不再管理該線程,如果b原來有線程,則原有線程被析構,管理新線程。
5、子線程分離
detach() 以后就失去了對線程的所有權,不能再調用join了,因為線程已經分離出去了,不再歸該實例管了。判斷線程是否還有對線程的所有權的一個簡單方式是調用joinable函數,返回true則有,否則為無。
#include <thread> #include <iostream> using namespace std; // 一個普通的函數 void fun(int num) { cout << "The function child thread begin...\n"; cout << "I come from function fun(): " << num << '\n'; cout << "The function child thread end...\n"; cout << endl; } // 一個函數類,實現了operator()方法 class Fun { public: void operator()(int num) { cout << "The class child thread begin...\n"; cout << "I come from class Fun: " << num << '\n'; cout << "The class child thread end...\n"; cout << endl; } }; int main() { cout << "Main thread begin..." << '\n'; cout.sync_with_stdio(true); // 設置輸入流cout是線程安全的 thread t_1(fun, 1); // 新建線程,第一個參數是函數指針,第二個參數是函數的參數(第二個參數是可變長參數) t_1.join(); // join方法數會阻塞主線程直到目標線程調用完畢,即join會直接執行該子線程的函數體部分 thread t_2(fun, 2); t_2.detach(); // detach方法不會阻塞任何線程,目標線程就成為了守護線程,駐留后台運行 Fun oFun; thread t_3(ref(oFun), 3); //這里新建線程,使用對象進行初始化,這里的通過ref傳遞的是oFun本身而不是其拷貝 t_3.join(); cout << "Main thread end..." << endl; return 0; }