std::async、std::future创建后台任务并返回值
std::async是一个函数模板,用来启动一个异步任务,启动起来一个异步任务之后,它返回一个std::future对象,这个对象是个类模板。
异步任务:就是自动创建一个线程,并开始 执行对应的线程入口函数,它返回一个std::future对象,这个std::future对象中就含有线程入口函数所返回的结果,我们可以通过调用future对象的成员函数get()来获取结果。
“future”将来的意思,也有人称呼std::future提供了一种访问异步操作结果的机制,就是说这个结果你可能没办法马上拿到,但是在不久的将来,这个线程执行完毕的时候,你就能够拿到结果了,所以,大家这么理解:future中保存着一个值,这个值是在将来的某个时刻能够拿到。
std::future对象的get()成员函数会等待线程执行结束并返回结果,拿不到结果它就会一直等待,有点像join(),但它可以获取结果。
1 #include <thread> 2 #include <iostream> 3 #include <list> 4 #include <map> 5 #include <mutex> 6 #include <future> 7 using namespace std; 8 class A { 9 public: 10 int mythread(int mypar) { 11 cout << mypar << endl; 12 return mypar; 13 } 14 }; 15 16 17 int mythread() { 18 cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; 19 std::chrono::milliseconds dura(5000); 20 std::this_thread::sleep_for(dura); 21 cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; 22 return 5; 23 } 24 25 26 int main() { 27 A a; 28 int tmp = 12; 29 cout << "main" << "threadid = " << std::this_thread::get_id() << endl; 30 std::future<int> result1 = std::async(mythread); 31 cout << "主子并行........" << endl; 32 cout << result1.get() << endl; //卡在这里等待mythread()执行完毕,拿到结果,只能调用一次 33 34 //类成员函数 35 std::future<int> result2 = std::async(&A::mythread, &a, tmp); //参数是对象引用才能保证线程里执行的是同一个对象 36 cout << result2.get() << endl; 37 cout << "good luck" << endl; 38 return 0; 39 }
通过向std::async()传递一个参数,改参数是std::launch类型(枚举类型),来达到一些特殊的目的:
1、std::lunch::deferred:
表示线程入口函数调用被延迟到,std::future的wait()或者get()函数调用时才执行;
如果wait()或者get()没有被调用,则不会执行。实际上根本就没有创建。(实际上延迟调用,并没有创建新线程,是在主线程中调用的线程入口函数)。
2、std::launch::async
在调用async函数的时候就开始创建线程。async()这个函数默认用的就是std::launch::async标记。
std::packaged_task:打包任务,把任务包装起来。
类模板,它的模板参数是各种课调用对象,通过packaged_task把各种可调用对象包装起来,方便将来作为线程入口函数。(算了,不是很懂!)
1 #include <thread> 2 #include <iostream> 3 #include <list> 4 #include <map> 5 #include <mutex> 6 #include <future> 7 using namespace std; 8 9 int mythread(int mypar) { 10 cout << mypar << endl; 11 cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; 12 std::chrono::milliseconds dura(5000); 13 std::this_thread::sleep_for(dura); 14 cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; 15 return 5; 16 } 17 18 19 int main() { 20 int tmp = 12; 21 cout << "main" << "threadid = " << std::this_thread::get_id() << endl; 22 std::packaged_task<int(int)> mypt(mythread); //我们把函数mythread通过packaged_task包装起来 23 std::thread t1(std::ref(mypt), 1); 24 t1.join(); 25 std::future<int> result = mypt.get_future(); 26 //std::future对象里包含有线程入口函数的返回结果,这里result保存mythread返回的结果。 27 cout << result.get() << endl; 28 cout << "good luck" << endl; 29 return 0; 30 }
std::promise,类模板
我们能够在某个线程中给它赋值,然后我们可以在其他线程中,把这个值取出来。
1 #include <thread> 2 #include <iostream> 3 #include <list> 4 #include <map> 5 #include <mutex> 6 #include <future> 7 using namespace std; 8 9 void mythread(std::promise<int> &tmp, int clac) { 10 cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl; 11 std::chrono::milliseconds dura(5000); 12 std::this_thread::sleep_for(dura); 13 cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl; 14 int result = clac; 15 tmp.set_value(result); //结果保存到了tmp这个对象中 16 return; 17 } 18 19 vector<std::packaged_task<int(int)>> task_vec; 20 21 int main() { 22 std::promise<int> myprom; 23 std::thread t1(mythread, std::ref(myprom), 180); 24 t1.join(); //在这里线程已经执行完了 25 std::future<int> fu1 = myprom.get_future(); //promise和future绑定,用于获取线程返回值 26 auto result = fu1.get(); 27 cout << "result = " << result << endl; 28 }
总结:通过promise保存一个值,在将来某个时刻我们通过吧一个future绑定到这个promise上,来得到绑定的值