C++并发与多线程(笔记一)

一、std::async、std::future创建后台任务并返回值

  • std::async:是一个函数模板,用来启动一个异步任务,启动起来一个异步任务之后,它会返回一个std::future对象
  • std::future:是一个类模板,std::future对象里面就含有线程入口函数所返回的结果,我们可以调用future对象的成员函数get来得到结果。future含有“将来的意思”,有人也称呼std::future提供了一种访问异步操作结果的机制,就是说这个结果没有办法马上拿到,但不久的将来,等线程执行完毕的时候,就能拿到结果了。
  • 异步任务:自动创建一个线程并开始执行对应的线程入口函数
  • std::launch:是一个枚举类型,向std::async()传递一个该参数。可以表示不同的意义:
    a)std::launch::deferred:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行,并且是直接在主线程中执行线程入口函数,相当于是一个延迟调用;如果没调用wait()或者get()函数,那么就不会执行线程入口函数
    b)std::launch::async:立即创建一个子线程并执行,std::async默认使用std::launch::async标记。
1.1 将函数作为线程入口函数
#include<iostream>
#include<thread>
#include<future>
using namespace std;

int mythread()
{
   cout<<"mythread() start "<<"threadid = "<<std::this_thread::get_id()<<endl;  //打印线程id值
   std::chrono::milliseconds dura(5000);  //休息5s
   std::this_thread::sleep_for(dura);    
   cout<<"mythread() end "<<"threadid = "<<std::this_thread::get_id()<<endl;  //打印线程id值
   return 5;
}
int main()
{
	cout<<"main"<<"thread_id = "<<std::this_thread::get_id()<<endl;
	std::future<int> result = std::async(mythread);  //创建一个线程并开始执行
	cout<<"continue.....!"<<endl;
	int def;
	def = 0;
	cout<<result.get()<<endl;  //获取future的结果
	return 0;
}
  • 主线程执行到result.get()时,会卡在这里,等待mythread执行完毕,拿到结果,才会继续执行下去。
  • result.wait() 也会等待线程执行完毕,但不会返回结果,类似于join()
  • result.get() 只能调用一次,不能调用多次,否者会报异常
1.2 将对象的成员函数作为线程入口函数
#include<iostream>
#include<thread>
#include<future>
using namespace std;
class A
{
public:
	int mythread(int mypar) //线程入口函数
	{
		cout << "mypar" << mypar << endl;
		cout << "mythread() start " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
		std::chrono::milliseconds dura(5000);  //休息5s
		std::this_thread::sleep_for(dura);
		cout << "mythread() end " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
		return 5;
	}

};

int main()
{
	cout << "main" << "thread_id = " << std::this_thread::get_id() << endl;
	A a;
	int tmpar = 0;
	std::future<int> result = std::async(&A::mythread,&a,tmpar);
	cout << "continue.....!" << endl;
	cout << result.get() << endl;  //获取future的结果
	return 0;
}
1.3 std::launch作为参数传递到std::async
#include<iostream>
#include<thread>
#include<future>
using namespace std;
class A
{
public:
	int mythread(int mypar) //线程入口函数
	{
		cout << "mypar" << mypar << endl;
		cout << "mythread() start " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
		std::chrono::milliseconds dura(5000);  //休息5s
		std::this_thread::sleep_for(dura);
		cout << "mythread() end " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
		return 5;
	}

};

int main()
{
	cout << "main" << "thread_id = " << std::this_thread::get_id() << endl;
	A a;
	int tmpar = 0;
	std::future<int> result = std::async(std::launch::deferred,&A::mythread,&a,tmpar);
	cout << "continue.....!" << endl;
	//cout << result.get() << endl;  //获取future的结果
	return 0;
}
  • 当使用std::launch::deferred时,若没有执行get()时,mythread线程都没有被创建出来,mythread()函数也没有被执行;若执行get(),发现子线程的id和主线程的id是一致的,没有创建出新线程,是在主线程中执行的mythread()函数。

二、std::packaged_task

  • 打包任务,把任务包装起来
  • 是个类模板,它的模板参数是各种可调用对象
  • 通过std::packaged_task 来把各种可调用对象包装起来,方便作为将来的线程入口函数
#include<iostream>
#include<thread>
#include<future>
using namespace std;

int mythread(int mypar) //线程入口函数
{
	cout << "mypar" << mypar << endl;
	cout << "mythread() start " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
	std::chrono::milliseconds dura(5000);  //休息5s
	std::this_thread::sleep_for(dura);
	cout << "mythread() end " << "threadid = " << std::this_thread::get_id() << endl;  //打印线程id值
	return 5;
}


int main()
{
	cout << "main" << "thread_id = " << std::this_thread::get_id() << endl;
	std::packaged_task<int(int)> mypt(mythread);    //相当于把函数mythread()包装起来
	std::thread t1(std::ref(mypt), 1);              //使用mypt创建一个线程
	t1.join();
	std::future<int> result = mypt.get_future();    //std::futute包含有线程函数mythread()的返回结果
	cout <<result.get()<< endl;
	cout << "main threadid = " << std::this_thread::get_id() << " end" << endl;
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值