C++11之future(二)
如果有两个线程,其中一个线程想要获取另一个线程的返回值,该怎么办?
于是接下来要谈的package_task就是为了解决这个问题而诞生的。
// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include<random> #include<iostream> #include<vector> #include<thread> #include<algorithm> #include<future> using namespace std; int mythread_one() { cout << "子线程1开始执行了,id:" << this_thread::get_id() << endl; cout << "子线程1执行任务中...." << endl; this_thread::sleep_for(chrono::seconds(3)); cout << "子线程1任务结束了" << endl; return 5; } void mythread_two(future<int> &ps) { cout << "子线程2开始执行了" << endl; auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程2任务执行结束" << endl; } int main() { //首先用pack_task包裹线程 packaged_task<int(void)> tp(mythread_one); //通过包裹的对象获取到future对象 future<int> a = tp.get_future(); //创建线程 thread th_one(ref(tp)); //让线程先执行起来 th_one.join(); thread th_two(mythread_two,ref(a)); th_two.join(); return 0; }
如果有多个线程,都想要获得该值,用这个函数可以做到吗?
下面看截取的这段代码:
void mythread_two(future<int> &ps) { cout << "子线程2开始执行了" << endl; auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程2任务执行结束" << endl; }
如果变为如下:
void mythread_two(future<int> &ps) { cout << "子线程2开始执行了" << endl; auto x = ps.get(); auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程2任务执行结束" << endl; }
多加了一行get()语句,经过程序运行是会抛异常的。
解释:get()函数内部实现是移动的语义,也就是说第一次调用后,里面的值已经被移动走了,如果再次调用get()的话,里面的值就为空了。
那该如何解决多线程同时想要获取一个线程资源的方法呢?于是share_future就出现了,下面把代码进行变换:
// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include<random> #include<iostream> #include<vector> #include<thread> #include<algorithm> #include<future> using namespace std; int mythread_one() { cout << "子线程1开始执行了,id:" << this_thread::get_id() << endl; cout << "子线程1执行任务中...." << endl; this_thread::sleep_for(chrono::seconds(3)); cout << "子线程1任务结束了" << endl; return 5; } void mythread_two(shared_future<int> &ps) { cout << "子线程2开始执行了" << endl; auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程2任务执行结束" << endl; } void mythread_three(shared_future<int>& ps) { cout << "子线程3开始执行了" << endl; auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程3任务执行结束" << endl; } int main() { //首先用pack_task包裹线程 packaged_task<int(void)> tp(mythread_one); shared_future<int> a=tp.get_future(); thread th_one(ref(tp)); //让线程先执行起来 th_one.join(); thread th_two(mythread_two,ref(a)); thread th_three(mythread_three, ref(a)); th_two.join(); th_three.join(); return 0; }
如果用了share_future的话,调用get()就是值拷贝机制了,所以可以多次调用get().
所以即使像下面这样一样ok
void mythread_three(shared_future<int>& ps) { cout << "子线程3开始执行了" << endl; auto x = ps.get(); auto x = ps.get(); auto x = ps.get(); cout << "获取子线程1的值为:" << x << endl; cout << "子线程3任务执行结束" << endl; }