C++11多线程学习笔记(1)——std::thread

Thread只是一个类,Thread对象可以与实际运行的线程产生联系,利用thread对象对线程进行操作,但是实际线程的存亡与thread对象的存亡并无绝对的决定关系

1. 构造函数

1、默认构造函数
thread() noexept;//空的thread对象
2、初始化构造函数
template<class Fn,class…Args> 
	explicit thread(Fn && fn,Args && … args)

创建thread对象,并将会执行fn代表的函数,fn为可调用对象 ,其参数由args给出,依据变长模板的实例化标准。

3、移动构造函数
thread(thread&& x) noexcept;

x所代表的线程的任务被交由当前thread对象,x不再与之前关联的线程有关。

2. 其他成员函数

(1)get_id

获取当前进程ID,通过thread对象获得关联线程的ID,线程ID都是唯一标识的,因此可以通过thread对象调用get_id()来区分,但是thread对象间可以转交线程,因此move操作、detach操作后,get_id()来区分的方法变得不可靠。thread对象与线程脱钩后,通过其调用get_id()会返回当前线程的ID。

(2) joinable

bool joinable() const noexcept
    { return !(_M_id == id()); }

检查当前进程是否可以被join,由默认构造函数生成的thread不可被join,该对象调用joinable返回false,而如果一个线程被创建但是仍未join,那么该对象调用joinable会返回true。只有当thread对象与线程关联时,通过thread对象调用joinable可以返回true,断开关联后、thread对象转交后,调用joinable都会返回false。

(3) join

阻塞式简单执行线程,通过thread对象调用join,使得当前线程等待对象线程执行完毕返回,并使thread对象与线程断开,因此一个thread对象只能调用一次,除非它被move赋值。

(4)detach

非阻塞式执行线程,通过thread对象调用detach,使得当前线程继续执行,thread对象创建的线程转入后台运行,并使thread对象与线程断开,一个thread对象只能调用一次,除非它被move赋值过。
【例1】

#include <iostream>
#include <thread>
#include <chrono>

void func1(int a,int b){std::cout << a + b << std::endl;}
void func2(){std::cout << "Func 2\n";}

int main()
{
	std::thread t1(func1, 1, 2);//变长模板模式,函数指针调用
	std::thread t2(func2);

	if (t1.joinable())
		std::cout << "Thread t1 is joinable\n";
	else
		std::cout << "Thread t1 is not joinable\n";
	if (t2.joinable())
		std::cout << "Thread t2 is joinable\n";
	else
		std::cout << "Thread t2 is not joinable\n";

	std::cout << "T1's ID is :\t" << t1.get_id() << std::endl
		<< "T2's ID is :\t" << t2.get_id() << std::endl;

	t1.join();
	t2.detach();
return 0; 
}
输出结果:
Thread t1 is joinable
Thread t2 is joinable
T1's ID is :    2724
T2's ID is :    12652
3
Func 2

(5)std::swap

交换量thread对象挂钩线程的底层句柄,可理解为交换了线程实体(存疑)。std::swap(Thread1,Thread2),Thread1.swap(Thread2)均可用。
【例2】

#include <iostream>
#include <thread>
#include <chrono>

void func1(int a,int b)
{
	std::cout << a + b << std::endl;
}
void func2()
{
	std::cout << "Func 2\n";
}

int main()
{
	std::thread t1(func1, 1, 2);
	std::thread t2(func2);
	std::thread t3(func1, 2, 3);
	std::thread t4(func2);
	if (t1.joinable() && t2.joinable())
	{
		t1.join();
		t2.join();
	}
	std::cout << "Swap t1 and t2 after join\n";
	std::swap(t1, t2);
	std::cout <<"t1's id:"<< t1.get_id() << std::endl;
	std::cout <<"t2's id:"<< t2.get_id() << std::endl;
	// t1与t2的id均为0,即当前线程(主线程)id,因为它们都join过了,thread对象与线程脱钩.
	std::swap(t3, t4);//所以只能在thread对象与线程脱钩之前swap
	std::cout << "\nt3 after swap:\n";
	t3.join(); 
	std::cout << "\nt4 after swap:\n";
	t4.join();
	
	return 0;
}

(6)native_handle

返回thread对象挂钩线程的本地句柄。

(7)hardware_concurrency

【static】
检测硬件并发特性,返回当前平台可支持的最大线程并发数目,仅供参考的系统提示(hint)。

3. this_thread

std::this_thread是thread类内一个命名空间

(1)this_thread::get_id

获取当前进程ID

namespace this_thread 
{
	_NODISCARD thread::id get_id() noexcept;
}

(2)this_thread::sleep_for

使当前线程休眠一段时间(_Rel_time):不过往往休眠的时间会超过这个数值,可以通过更高精度的计时器验证。

template< class Rep, class Period >
 void sleep_for( const std::chrono ::duration<Rep,Period>& sleep_duration );

(3)this_thread::sleep_until

使当前线程休眠到某个时间点(_Abs_time)。

template< class Clock, class Duration >
  void sleep_until( const std::chrono::time_point
  						<Clock,Duration>& sleep_time );

(4)this_thread::yield

放弃当前线程的执行,让出自己的时间片给其他线程使用,特定适用于CPU非常忙碌的时候,否则建议使用sleep_for()与sleep_until(),以便于其他目的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fanshaoliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值