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;
}

 

posted @ 2020-08-20 18:47  sunshine_gzw  阅读(353)  评论(0编辑  收藏  举报