C++11: std::thread和std::this_thread

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;
}
相关文章
相关标签/搜索