C++11多线程编程 9.async、future、packaged_task、promise

#include<iostream>
#include<string>
#include<thread>
#include<asyncinfo.h>
#include<future>
#include<vector>
using namespace std;
class A
{
public:
    int mythread2(int mypar)
    {
        cout << mypar << endl;
        cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
        std::chrono::milliseconds dura(5000);//定义一个5秒的时间
        std::this_thread::sleep_for(dura);//休息了五秒
        cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
        return 5;
    }
};
int mythread()
{
    cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
    std::chrono::milliseconds dura(5000);//定义一个5秒的时间
    std::this_thread::sleep_for(dura);//休息了五秒
    cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
    return 5;
}

int mythread3(int mypar)
{
    cout << mypar << endl;
    cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
    std::chrono::milliseconds dura(5000);//定义一个5秒的时间
    std::this_thread::sleep_for(dura);//休息了五秒
    cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
    return 5;
}

//std::promise
void mythread5(std::promise<int> &tmpp ,int calc) {//操作的变量为整形,返回的是int,运算结果是整型,所以是int
    //做一系列复杂运算。
    calc++;
    calc *= 10;
    //做其他运算,花费了五秒。
    std::chrono::milliseconds dura(5000);//定义一个5秒的时间
    std::this_thread::sleep_for(dura);//休息了五秒
    int result = calc;//保存结果
    tmpp.set_value(result);//结果我保存到了tmpp这个对象中
    return;
}
//创建一个新线程,用上面线程的值
void mythread6(std::future<int> &tmpp)
{
    auto result = tmpp.get();
    cout << result << endl;
    return;

}
int main()
{
    /*    (1)std::async、std::future创建后台任务并返回
    *        希望线程返回一个结果
    *        std::async是一个函数模板,用来启动一个异步任务,启动后,返回一个std::future对象,这是一个类模板
    *            什么叫“启动一个异步任务”,就是自动创建一个线程,并开始执行对应的线程入口函数,他返回一个std::future对象
    *                这个对象里面就含有这个线程入口函数所返回的结果(线程返回的结果),我们可以通过调用这个future对象的成员函数get()来获取结果。
    *            “future”将来的意思,有人也称呼std::future提供了一种访问异步操作结果的机制,就是说这个结果你可能没有办法马上拿到,但是不久的将来
    *                (线程执行完毕)的时候,你就能拿到结果了,所以大家就这么理解:这个future里会保存一个值。在将来的某个时刻能够拿到    
                我们通过额外向std::async()传递一个参数,该参数的类型是std::lunnch类型(枚举类型),来达到一些特殊的目的。
                    a)std::launch::deferred;表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行。
                        问题:那如果wait()或者get()没有执行,这个线程会执行吗?    
                        答案:线程根本就没创建,所以也没执行。
                      std::launch::deferred;延迟调用,并且没有创建新线程,是在主线程中调用的线程入口函数;
                    b)std::launch::async,在调用async函数的时候就开始创建线程。
                        async()函数默认的用的是std::launch::async | std::launch::deferred 系统会根据自己需求选择二者其一。
            经过package_task或者std::promise打包后用get_future()获得future对象,后面还需要用get得到该对象保存的值。如果没有打包,原生的future类对象则直接用get获得值
    *    (2)std::package_task :打包任务,把任务包装起来
    *        是个类模板,它的模板参数是各种可调用对象(函数,类中圆括号重载,类对象),通过std::package_task将各种可调用对象包装起来,方便作为线程入口函数来调用。
    *        package_task包装起来的可调用对象还可以直接调用,所以从这个角度讲,package_task,也是一个可调用对象。
        (3)std::promise
            类模板,作用:我们在某个线程中给他赋值,在其他线程中把这个值取出来使用。
            通过promise保存一个值,在将来某个时刻我们通过吧一个future绑定到这个promise上来得到这个绑定的值
    *    (4)小结 :到底怎么用,什么时候用
    *        我们学这些东西的目的,并不是把他们都用在实际开发中,
    *        相反,如果咱们能够用最少的东西写出稳定高效的多线程程序,更值得赞赏;
    *        我们为了成长,必须要阅读一些高手的代码,从而加速实现自己代码的积累,我们的技术就会有大幅度的提升。
    *        
    */

    //下列程序通过std::future对象的get()成员函数等待线程执行结束并返回结果。
    //这个get函数很牛,不拿到将来的返回值誓不罢休,不拿到值我就卡在这里等待拿值。
    A a;
    cout << "main" << " thread is " << std::this_thread::get_id() << endl;
    //std::future<int> result = std::async(mythread);//创建一个线程并开始执行。绑定关系,如果线程入口函数有参数,那么从第二个参数开始给参数的值
                                            //通过系统的async创建一个异步任务,也就是开启一个新线程,线程入口函数为mythread
    //std::future<int> resule = std::async(&A::mythread2,&a,12);//第一个参数为成员函数的地址,第二个为对象引用,才能保证线程里边用的是同一个对象。,从第三个开始给参数的地址。
    //std::future<int> result = std::async(std::launch::deferred, mythread);//系统延迟执行,如果不调用get不执行。
    std::future<int> result = std::async(std::launch::async, mythread);//系统默认标记,不需要等get或者wait就可以创建线程并且执行。

    cout << "continue.....!" << endl;
    int def;
    cout << result.get();//卡在这里等待mythread()执行完毕,拿到结果。
    // result.get();//不能调用多次,调用多次就报异常,只能调用一次
    result.wait();//只是等待,不接收返回值。类似于join


    //std::pacckage_task
    cout << "main" << "thread id =" << std::this_thread::get_id() <<  endl;
    std::packaged_task<int(int)> mypt(mythread);//我们把函数mythread通过package_task包装起来
    std::thread t1(std::ref(mypt),1);//ref纯引用,防止复制,1为线程入口函数的参数,线程直接开始执行。
    t1.join();//等待线程执行完毕
    std::future<int> result1 = mypt.get_future();//std::future对象里包含有线程入口函数的返回结果,这里result保存muthread返回的结果。
    cout << result1.get() << endl;

    //可以包装lambda表达式
    std::packaged_task<int(int)> mypt2([](int mypar) {//第一个int为返回类型为整形,第二个int为参数为整形,将这种函数包装到package_task里面去。
        cout << mypar << endl;
        cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
        std::chrono::milliseconds dura(5000);//定义一个5秒的时间
        std::this_thread::sleep_for(dura);//休息了五秒
        cout << "mythred() start" << "thred id =" << std::this_thread::get_id() << endl;//打印新线程的ID
        return 5;
        });
    //调用package_task ,没有创建线程,相当于函数调用。
    //mypt2(105);
    //std::future<int> result =mypt2.getfuture();
    //cout<<result.get()<<endl;

    vector<std::packaged_task<int(int)>> mypt4;
    mypt4.push_back(std::move(mypt2));//容器,这里mypt2为空了。

    std::packaged_task<int(int)> mypt5;
    auto itor = mypt4.begin();
    mypt5 = std::move(*itor);//换一个位置。
    mypt4.erase(itor);//删除第一个元素,迭代已经失效了,所以后续代码不可以再使用itor
    mypt5(102);
    std::future<int> result1 = mypt5.get_future();
    cout << result1.get();

    //std::promise
    std::promise<int> myprom;//声明一个std::promise对象myprom,保存的值类型为int;
    std::thread ti(mythread5, std::ref(myprom), 180);
    ti.join();
    //获取结果值
    std::future<int> ful = myprom.get_future();//promise和future绑定,用于获取线程返回值。
    auto resultt = ful.get();//会立即拿到。
    cout << "result=" << resultt << endl;


    //让另一个线程用上面这个代码的线程所返回的值
    std::thread myproo(mythread6, std::ref(ful));
    myproo.join();//等待myproo线程执行完毕 

}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值