線程的創建
? ? ? ? 用std::thread創建線程非常簡單,只需要提供線程函數或者線程對象即可,并可以同時指定線程函數的參數。下面是創建線程的示例:
#include <thread>
#include <iostream>
using namespace std;void func()
{cout << "thread run...." << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t(func);t.join();cout << "main over..." << endl;return 0;
}
? ? ? ? 在上例中,函數func將會運行于線程對象t中,join函數將會阻塞,直到線程函數執行結束,如果線程函數有返回值,返回值將被忽略。
? ? ? ? 如果不希望線程被阻塞執行,可以調用線程的detach方法,將線程和線程對象分離。比如下面的例子:
#include <thread>
#include <iostream>
#include <string.h>
using namespace std;void func()
{cout << "thread run...." << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t(func);t.detach();///做其他事情cout << "main over..." << endl;while(1){if(getchar()){break;}}return 0;
}
? ? ? ? 通過detach,線程就和線程對象分離了,讓線程作為后臺線程去執行,當前線程也不會阻塞了。但需要注意的是,detach之后就無法再和線程發生聯系了,比如detach之后就不能再通過join來等待 線程執行完成,線程何時執行完成我們也無法控制了。
? ? ? ? 線程還可以接收任意個數的參數:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
using namespace std;void func(int i, double db, const string& str)
{cout << i << endl;cout << db << endl;cout << str << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t(func, 1, 2, "test");t.detach();getchar();return 0;
}
? ? ? ? 上面的例子將會輸出:
1
2
test
? ? ? ? 使用這種方法創建線程很方便,但需要注意的是,std::thread出了作用域之后將會析構,這時如果線程函數還沒有執行完就會發生錯誤,因此,需要保證線程函數的生命周期在線程變量std::thread的生命周期之內。
? ? ? ? 線程不能復制,但可以移動,例如:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
using namespace std;void func()
{cout << "111111111111" << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t(func);std::thread t1(std::move(t));t1.join();getchar();return 0;
}
? ? ? ? 線程被移動之后,線程對象t將不在不代表任何線程了。另外,還可以通過std::bind或lambda表達式來創建線程,代碼如下:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
#include <functional>
using namespace std;void func(int a, double db)
{cout << a << "\t" << db << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t1(std::bind(func, 1, 2));std::thread t2([](int a, double db){ cout << a << "\t" << db << endl;}, 5, 6);t1.join();t2.join();getchar();return 0;
}
? ? ? ? 需要注意的是線程對象的生命周期,比如下面的代碼:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
#include <functional>
using namespace std;void func(int a, double db)
{cout << a << "\t" << db << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t1(func, 1, 2);///join函數注釋了,會有異常發生///t1.join();return 0;
}
? ? ? ? 上面的代碼運行可能會拋出異常,因為線程對象可能先于線程函數結束,應該保證線程對象的生命周期在線程函數執完時仍然存在。可以通過join方法來阻塞等待線程函數執行完,或者通過detach方法讓線程在后臺執行。
線程的基本用法
獲取當前信息
? ? ? ? 線程可以通過當前線程的ID,還可以獲取CPU核心數量,例如:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
#include <functional>
using namespace std;void func()
{
}/// g++ thread.cpp -lpthread
int main()
{std::thread t1(func);cout << t1.get_id() << endl;cout << std::thread::hardware_concurrency() << endl;t1.join();return 0;
}
線程休眠
? ? ? ? 可以使當前線程休眠一定時間,代碼如下:
#include <thread>
#include <iostream>
#include <string.h>
#include <string>
#include <functional>
using namespace std;void func()
{std::this_thread::sleep_for(std::chrono::seconds(3));cout << "time out" << endl;
}/// g++ thread.cpp -lpthread
int main()
{std::thread t1(func);t1.join();return 0;
}
? ? ? ? 在上面的例子中,線程將會休眠3秒,3秒之后將打印time out。