记录:学习多线程(八):async,future,packaged_task,promise

//std::async,std::future创建后台任务并返回值
//std::packaged_task
//std::promise
//小结

#include<map>
#include<string>
#include<thread>
#include<list>
#include<mutex>
#include<future>

using namespace std;


/*int mythread(int mypar){
	cout<<mypar<<endl;
	cout<<"mythread() start"<<"thread = " <<std::this_thread:get_id()<<endl;//打印新线程
	std::chrono::millionseconds dura(5000);//定义休息5秒的时长
	std::this_thread::sleep_for(dura);//休息一定时长
	cout<<"mythread() end"<<"thread = " << std::this_thread:get_id(<<endl;//打印新线程
	return 5;
}*/

void mythread(std::promise<int> &tmpp,int calc){//大家注意第一个参数
	//做一系列复杂的操作
	calc++;
	calc *= 10;
	//做其他运算,比如整数花费了5秒钟,
	std::chrono::millionseconds dura(5000);//定义休息5秒的时长
	std::this_thread::sleep_for(dura);//休息一定时长
	
	//终于计算出结果了
	int result = calc;//保存结果
	tmpp.set_value(result);//结果我保存到了tmpp这个对象中;
	return;
}

//vector<std::package_task<int(int)> >mytask;//容器

void mythread2(std::future<int> &tmpf){
	auto result = tmpf.get();
	cout<<"mythread2 result"<<result<<endl;
	return;
}

int main(){
	/*std::async,std::future创建后台任务并返回值
	希望线程返回一个结果;

	std::async是一函数模板,用来启动一个异步任务,启动一个异步任务之后,
	他返回一个std::future对象,std::future是一个类模板,
	什么叫启动一个异步任务?就是自动创建一个线程并执行对应的线程入口函数
	,它返回一个std::future对象,这个std::future对象立便就含有线程入口函
	数所返回的结果(线程返回的结果),我们可以调用future对象的成员函数get
	()来获取结果;
	future将来的意思,有人也称呼std::future提供了一种访问异步操作结果的
	机制,就是说这个结果,你可能没办法马上拿到,在线程执行完毕的时候,你
	就能够拿到结果了,所以大家就这么理解:这个future里会保存一个值,这个
	值会在将来的某个时刻能够拿到。

	下列程序通过std::future对象的get()成员函数等待线程结束并返回结果
	这个get()函数很牛,不拿到返回的值,誓不罢休,不拿到值我就卡在这里等
	待拿值;

	我们通过额外向std::async()传递一个参数,该参数类型是std::lunch类型;
	(枚举类型),来达到一些特殊的目的
	//a)std::launch::deferred:表示线程入口函数调用延长到std::future的
	wait()或者get()函数调用才执行,那如果wait()或者get()没有被调用,那
	么线程会执行吗?没执行,实际上,线程根本没有创建
	std::launch::deferred:延迟调用,并且没有创建新线程,是在主线程中调
	用的线程入口函数;
	
	//b)std::launch::async,在调用async函数的时候开始创建线程;
	async()函数,默认用的就是std::launch::async标记
	
	A a;
	int tmppar = 12;
	第二个参数是对象引用,才能保证线程里面用的是同一个对象,
	cout<<"main"<<"thread_id="<<std::this_thread::get_id()<<endl;
	std::future<int> resulet=std::async(std::launch::deferred,&A::mythread,&a,tmppar);
	cout<<"continue......!"<<endl;
	int def;
	def = 0;
	//result.wait()等待线程返回,本身并不返回结果。 
	cout<<result.get()<<endl;//只能用一次,不能用多次
	cout<<"l love china"<<endl;*/


	/*二:std::packaged_task:打包任务,把任务包装起来
	是一个类模板,它的模板参数是各种可调用对象;通过std::packaged_task把
	各种可调用对象包装起来,方便将来作为线程入口函数来调用
	packaged_task包装起来的可调用对象可以直接调用,所以从这个角度来讲,pa
	ckaged_task对象,也是一个可调用对象; 

	
	cout<<"main"<<"thread_id="<<std::this_thread::get_id()<<endl;
	std::package_task<int(int)> mypt(mythread);/*我们把函数mythread通
	过package_task包装起来
	std::thread t1(std::ref(myqt),1); /*线程直接开始执行,第二个参数作为i
	线程入口函数的参数,
	t1.join();//等待线程执行完毕。
	std::future<int>  result = mypt.get_future(); /*std::future对象里
	包含有线程入口函数的返回结果,result保存mythread返回的结果
	cout<< result.get()<<endl;
	cout<<"l love china"<<endl;*/
	
	//cout<<"main"<<"thread_id="<<std::this_thread::get_id()<<endl;
	
	//std::package_task<int(int)> mypt([](int mypar){
	//cout<<mypar<<endl;
	//cout<<"mythread() start"<<"thread = " <<std::this_thread:get_id()<<endl;//打印新线程
	//std::chrono::millionseconds dura(5000);//定义休息5秒的时长
	//std::this_thread::sleep_for(dura);//休息一定时长
	//cout<<"mythread() end"<<"thread = " << std::this_thread:get_id(<<endl;//打印新线程
	//return 5;
	});
	//std::thread t1(std::ref(myqt),1); /*线程直接开始执行,第二个参数作为i
	//线程入口函数的参数,*/
	//t1.join();//等待线程执行完毕。
	//std::future<int>  result = mypt.get_future(); /*std::future对象里
	//包含有线程入口函数的返回结果,result保存mythread返回的结果*/
	//cout<< result.get()<<endl;
	//cout<<"l love china"<<endl;
	
	//mypt(105);//直接调用相当于函数调用
	//std::future<int>  result = mypt.get_future();
	//cout<< result.get()<<endl;
	
	//mytasks.push_back(std::move(mypt));/*容器,这里用了移动语义,进去之
	//后mypt就为空了*/

	//std::packaged_task<int(int)> mypt2;
	//auto iter = mytasks.begin();
	//mypt2 = std::move(*iter);/*移动语义*/
	//mytasks.erase(iter);/*删除一个元素,迭代器已经失效,所以后续代码不可
	//以再使用iter,*/ 	
	//std::future<int>  result = mypt2.get_future(); /*std::future对象里
	//包含有线程入口函数的返回结果,result保存mythread返回的结果*/
	//cout<< result.get()<<endl;
	//return 0;
	
	//三:std::promise,类模板
	/*我们能够在某个线程中赋值,然后我们可以在其他线程中,把这个值取出来
	用,*/
	/*总结:通过promise保存一个值,在将来某个时刻通过一个future绑定到这
	promise上来得到这个绑定的值;*/
	std::promise<int> myprom;/*声明一个std::promise对象myprom,保存的值
	类型为int*/
	std::thread t1(mythread,std::ref(myprom),180);
	t1.join();
	//获取结果值
	std::future<int> fu1 = myprom.get_future(); /*promise和future绑定,
	用于获取线程返回值*/
	//auto result = fu1.get();//get只能调用一次,不能调用多次 
	//cout<<"result = "<< result <<endl;

	std::thread t2(mythread2,std::ref(ful));
	t2:join();//等mythread2执行完毕
	
	cout<<"i love china"<<endl;
	
	return 0;
}

小结:到底怎么用,什么时候用;

我们学习这些东西的目的,并不是要把他们用在自己的实际开发中。
相反,如果我们能够用最少的东西能够写出一个稳定,高效的多线程程序,更值得赞赏;

我们为了成长,必须要阅读一些高手写的代码,从而快速实现自己代码的积累,我们的技术就会有一个大幅度的提升;

老师更愿意将学习这些内容的理由解释为:为我们将来能够读懂高手甚至大师写的代码铺路,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值