C++11起,標準庫除了提供std::async(),這樣的高級線程接口之外,還提供了更加簡單的std::thread,咱們只須要聲明一個std::thread對象,而後傳遞進去函數(function注意這裏並非callable object)進去,以及該function可接受的參數,而後要麼等待它結束,要麼將他卸離(detach).java
若是std::thread想要使用 callable object須要配合std::packaged_task.ios
咱們能夠看一下std::thread對傳入的function的調用:dom
template<typename Func, typename ...Types, typename = typename std::enable_if< !std::is_member_pointer<typename std::decay<Func>::type>::value, void>::type> auto invoke(Func&& func, Types&&... args)->decltype((std::forward<Func>(func))(std::forward<Types>(args)...)) { return (std::forward<Func>(func))(std::forward<Types>(args)...); }
首先來看一個例子:async
#include <iostream> #include <thread> #include <chrono> #include <random> #include <exception> void doSomething(const int& number, const char& c) { try { std::default_random_engine engine(42 * static_cast<int>(c)); std::uniform_int_distribution<int> distribution(10, 100); for (int i = 0; i < number; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(distribution(engine))); std::cout.put(c).flush(); } }catch (const std::exception& e) { std::cerr << "THREAD-EXCEPTION (thread " << std::this_thread::get_id() << "): " << e.what() << std::endl; }catch (...) { std::cerr << "THREAD-EXCEPTION (thread " << std::this_thread::get_id() << ")" << std::endl; } } int main() { try { std::thread t1(doSomething, 5, '.'); std::cout << "- started fg thread " << t1.get_id() << std::endl; for (int i = 0; i < 5; ++i) { std::thread temp_thread(doSomething, 10, 'a' + i); std::cout << "-detach started thread bg thread " << temp_thread.get_id() << std::endl; temp_thread.detach(); } std::cin.get(); std::cout << "- join fg thread " << t1.get_id() << std::endl; t1.join(); }catch (const std::exception& e) { std::cerr << "EXCEPTION: " << e.what() << std::endl; } return 0; }
std::thread的構造函數:函數
thread() noexcept; template <class Fn, class... Args> explicit thread (Fn&& fn, Args&&... args); thread (const thread&) = delete; thread (thread&& x) noexcept;
1,默認構造函數,構建一個沒有任何callable object對象的線程.this
2,顯式構造函數(也就意味着不支持隱式的類型轉換),接受一個function以及該function可接受的參數(注意這些參數都是by-value的形式傳遞進去的,也就是拷貝).atom
3,被刪除了的copy-constructor,也就是說std::thread是不支持copy的.spa
4,移動構造函數,被移動的std::thread處於無效狀態,當前std::thread得到被移動對象的callable object以及callable object可接受的參數.線程
std::thread::detachcode
調用該函數使得當前std::thread對象所與母體分離(detach),也就是說使得當前std::thread運行於後臺不受任何控制(這樣也隨之帶來一個問題,可能main線程都結束了該線程還在運行).
void detach();
std::thread::get_id
1,若是該std::thread是joinable狀態(joinable狀態後面會提到),那麼就返回一個獨一無二的(unique)的當前std::thread的id(std::thread::id).
2,若是該std::thread是not joinable狀態,返回std::thread::id();
#include <iostream> #include <thread> #include <chrono> std::thread::id main_thread_id = std::this_thread::get_id(); void is_main_thread() { if (main_thread_id == std::this_thread::get_id()) { std::cout << "main-thread!" << std::endl; }else { std::cout << "not main thread! " << std::endl; } } int main() { is_main_thread(); std::thread other_thread(is_main_thread); other_thread.join(); return 0; }
std::thread::joinable
該函數返回一個bool值:
1,若是當前std::thread對象是default-constructor構造出來的返回false.
2,若是當前std::thread對象被移動到了其餘std::thread對象返回false.
3,若是當前std::thread對象的detach()和join()被調用過了返回false.
bool joinable() const noexcept;
std::thread::join
block(阻塞)調用join()的線程,直到std::thread所在的線程完成,與此同時std::thread獨顯被設置爲not joinable.
void join();
std::thread::operator=
std::thread仍然是不支持copy-assign-operator(拷貝賦值運算符),可是支持move-assign-operator.
對於move-assign-operator須要注意的是:
1,噹噹前std::thread對象處於joinable狀態的時候對當前對象調用move-assign-operator,會terminal.
2,若是當前std::thread對象處於not joinable狀態那麼OK.
thread& operator= (thread&& rhs) noexcept; thread& operator= (const thread&) = delete;
------------------------------我是分割線----------------------------------
std::this_thread其中的this_thread是位於std這個命名空間中的命名空間.位於該命名空間中有幾個函數.這些函數通常都是用來輔助std::thread,std::async.
std::this_thread::get_id
返回一個獨一無二的當前線程的ID(通常也就是unsigned int類型).
thread::id get_id() noexcept;
std::this_thread::sleep_for
阻塞(block)正在調用該函數的線程一段時間.
template <class Rep, class Period> void sleep_for (const chrono::duration<Rep,Period>& rel_time);
std::this_thread::sleep_until
阻塞(block)正在調用該函數的線程直到指定的時間點(timepoint).
template <class Rep, class Period> void sleep_for (const chrono::duration<Rep,Period>& rel_time);
std::this_thread::yield
這個是個重點,能夠參考java和PHP的該函數.
該函數的主要做用是:使正在處於運行狀態的該線程,回到可運行狀態,以容許其餘具備相同優先級的線程得到先執行的機會。可是頗有可能該線程剛剛回到可執行狀態又被再次執行。
void yield() noexcept;
#include <iostream> #include <thread> #include <chrono> #include <atomic> std::atomic<bool> boolean(false); void doSomething(const int& id) { while (!boolean) { std::this_thread::yield();//注意這裏. } for (int i = 0; i < 1000000; ++i) { ; } std::cout << id; } int main() { std::thread threads[10]; for (unsigned int i = 0; i < 10; ++i) { threads[i] = std::thread(doSomething, i); } boolean = true; for (std::thread& ref_thread : threads) { ref_thread.join(); } std::cout << '\n'; return 0; }