异步任务std::async,std::future,std::packaged_task

1.packaged_task:打包函数线程

int mythread(int mypar)//The entrance function of thread 
{
    
    
	cout << "mypar is " << mypar << endl;
	cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
	return 5;
}
//main
int main{
    
    
	cout << "main threadID is: " << this_thread::get_id() << endl;
//2.0 package_task用来封装异步线程共享future数据到mypt
	//<int(int)>:<int>函数返回类型,(int)函数中传入参数的类型
	packaged_task<int(int)>mypt(mythread);
	//线程直接开始执行,第二个参数,作为线程入口函数的参数。
	thread t1(std::ref(mypt), 1);
	t1.join();
	future<int>result = mypt.get_future();
	
	//get only can be called one time
	cout <<"Result get:"<< result.get() << endl;//waiting mythread return the num 5.or it stuck the program
	//result.wait();//it Only wait the thread and don't return the value.
	cout << "Main end" << endl;
	return 0;
}

2.packaged_task 包装lambda
直接在主线程中书写子线程,packaged_task包装可调用对象

//main
int main{
    
    
cout << "main threadID is: " << this_thread::get_id() << endl;

std::packaged_task<int(int)>mypt([](int mypar)
{
    
    
	cout << "mypar is " << mypar << endl;
	cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
	return 5;
}

	cout << "main threadID is: " << this_thread::get_id() << endl;
	packaged_task<int(int)>mypt(mythread);
	//线程直接开始执行,第二个参数,作为线程入口函数的参数。
	thread t1(std::ref(mypt), 1);
	t1.join();
	future<int>result = mypt.get_future();
	
	//get only can be called one time
	cout <<"Result get:"<< result.get() << endl;
	//result.wait();//it Only wait the thread and don't return the value.
	cout << "Main end" << endl;
	return 0;
}

3.packaged_task的对象时一个可调用对象
packaged_task包装起来的可调用对象可以直接调用,所以他的对象也是可调用对象。
和主线程在同一个线程执行。

int main()
{
    
    
cout << "main threadID is: " << this_thread::get_id() << endl;

std::packaged_task<int(int)>mypt([](int mypar)
{
    
    
	cout << "mypar is " << mypar << endl;
	cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
	return 5;
}

//直接调用
//
mypt(100);
std::future<int>result=mypt.get_future();
cout<<result.get()<<endl;
}

4.vector来收集packaged_task

//返回<int>,传入(int)
vector<std::packaged_task<int(int)>>mytasks;//容器

int main()
{
    
    
cout << "main threadID is: " << this_thread::get_id() << endl;


std::packaged_task<int(int)>mypt(
[](int mypar)
{
    
    
	cout << "mypar is " << mypar << endl;
	cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
	return 5;
}
);
mytasks.push_back(std::move(mypt));//入容器。使用了移动语义,入容器后mypt为空
//取出vector中的mypt
std::packaged_task<int(int)>mypt2;
auto iter=mytasks.begin();//iter是一个指针
//*iter 就是iter所指向的对象mypt,移动了mypt函数=mypt2,但是vector mytask中还有一项
mypt2=std::move(*iter);
mytasks.erase(iter);//删除mytask中第一个元素(项),迭代失效。所以后续代码不可再使用iter
//mytasks为空
mypt2(123);//把123传递给mypar
std::future<int>result=mypt2.get_future();
cout<<result.get()<<endl;

return 0;

}

5.std::promise,类模板
我们能够在某个线程中给他赋值,然后我们可以在其他线程中,把这个值取出来用。
通过promise保存一个值,在将来的某个时刻我们通过把一个future绑定到这个promise上来得到这个绑定的值。

void mythread(std::promise<int>&tmp,int calc)
{
    
    
//operate the calc
calc++;
calc*=10;
//wait 5 S
chrono::millseconds dura(5000);
this_thread::sleep_for(dura);

int result=calc;//save the result of calc
tmp.set_value(result);
}

int main()
{
    
    
//declare a object,called myprom, of promise which saves the an int data;
std::promise<int>myprom; 
std::thread t1(mythread,std::ref(myprom),100);
t1.join();
//get the promise
std::future<int>ful=myprom.get_future();//get the return value of calc
auto result=ful.get();//get只能调用一次!!!
cout<<result<<endl;

}

6.多线程交互数据

void mythread(std::promise<int>&tmp,int calc)
{
    
    
//operate the calc
calc++;
calc*=10;
//wait 5 S
chrono::millseconds dura(5000);
this_thread::sleep_for(dura);

int result=calc;//save the result of calc
tmp.set_value(result);
}

void mythread2(std::future<int>&temp)
{
    
    
auto result=temp.get();
cout<<"This is thread2, the cala in thread1 is <<result<<endl;
}

int main()
{
    
    
promise<int> mTemp;
future<int> mFu;
thread t1(mythread,mTemp,100;
t1.join();
mFu=mTemp.get_future();
thread t2(mythread2,mFu);
t2.join();
return 0;
}

7.杂

//异步任务
//1.希望线程返回结果
//std::async,std::future 创建后台任务并返回值
//std::async
/*
std::async 是一个函数模板,用来启动一个异步任务,启动起来一个异步任务之后,他返回一个std::futrue对象
std::future 是一个类模板 ,提供了一种访问异步操作结果的机制,这个结果在不久的将来
线程执行完毕就可以拿到结果可以拿到。future(对象)里会保存一个值。
*/
//启动一个异步任务
/*
自动创建一个线程,并开始执行对应的线程入口函数。他返回一个std::future对象。
std::future 对象里就含有线程入口函数所返回的结果。(线程返回的结果)
我们可以通过调用future对象的成员函数get()来获取结果。
*/
//std::launch::deferred
/*
我们通过向std::async()传递一个参数,该参数的类型是std::lunch类型(枚举类型),来达到一些特殊的目的
std::launch::defered:表示线程入口函数被延迟到future的wait()或者get()函数被调用时才执行。
如果wait(),get()没被调用就不会创建线程,也不会调用。
launch::defered:延迟调用,并没有创建新线程,是在主线程中调用的线程入口函数。
*/
//std::launch::async
/*
在调用async函数的时候,就开始创建线程;
async()函数,默认用的就是std::launch::async标记
*/
//std::launch::deferred|std::launch::async
/*
可以生成,但是只有async功能有效,deferred功能无效
*/

//std::pack_task:打包任务,把任务包装起来
/*是个类模板,他的模板参数是各种可调用的对象;
通过std::packaged_task来把各种可调用对象包装起来方便将来作为线程入口函数来调用。*/

#include<map>
#include<string>
#include<thread>
#include<list>
#include<mutex>
#include<iostream>
#include<future>//future header lib
using namespace std;
//using std::cout;

//class A{
    
    
//public:
int mythread(int mypar)//The entrance function of thread 
{
    
    
	cout << "mypar is " << mypar << endl;
	cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
	return 5;
}
//};

int main()
{
    
    
	//A a;
	int tmppar = 12;

	cout << "main threadID is: " << this_thread::get_id() << endl;
	//std::future<int>result = std::async(mythread);//创建一个线程开始执行,绑定关系
	
	//The second para is a ref to ensure that the threads use the same data
	//future<int>result = std::async(&A::mythread, &a,tmppar);
	
	//std::launch::deferred,在主线程中延迟运行mythread函数
	//std::future<int>result = std::async(std::launch::deferred, &A::mythread, &a, tmppar);

	//std::launch::async
	//std::future<int>result = std::async(std::launch::async, &A::mythread, &a, tmppar);

	//std::launch::async|std::launch::deferred
	//"|"表示同时调用async和deferred参数
	//但是async的标记位0x1,deferred是0x2两个枚举标记位。
	//std::future<int>result = async(launch::async | launch::deferred, &A::mythread, &a, tmppar);
	
	//2.0 package_task用来封装异步线程共享future数据到mypt
	//<int(int)>:<int>函数返回类型,(int)函数中传入参数的类型
	packaged_task<int(int)>mypt(mythread);
	//线程直接开始执行,第二个参数,作为线程入口函数的参数。
	thread t1(std::ref(mypt), 1);
	t1.join();
	future<int>result = mypt.get_future();

	//2.1packaged_task包装一个lambda表达式,让其成为线程接口
	/*packaged_task<int(int)>mypt(//lambda开始[]
		[](int mypar) {
		cout << "mypar is " << mypar << endl;
		cout << " mythread() is runing,threadID is: " << this_thread::get_id() << endl;
		chrono::milliseconds dura(5000);
		this_thread::sleep_for(dura);
		cout << "mythread is ending,threadID is =" << this_thread::get_id() << endl;
		return 5; 
		}//lambda结束
	);*/

	//2.2直接调用封装接口
	/*mypt(100);
	std::future<int>result = mypt.get_future();
	cout<<result.get()<<endl;*/

	
	chrono::milliseconds dura(5000);
	this_thread::sleep_for(dura);
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;
	cout << "continue...!" << endl;



	//get only can be called one time
	cout <<"Result get:"<< result.get() << endl;//waiting mythread return the num 5.or it stuck the program
	//result.wait();//it Only wait the thread and don't return the value.
	cout << "Main end" << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/guanxunmeng8928/article/details/108364606