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; }