zoukankan      html  css  js  c++  java
  • 九、async、future、packaged_task、promise

    std::async、std::future创建后台任务并返回值。

    希望线程返回一个值。

    std::async是个函数模板,用来启动一个异步任务,返回一个std::future对象

    异步任务:自动创建一个线程并开始执行对应的线程入口函数,返回一个std::future对象。

    这个对象里面就含有线程函数所返回的结果(线程返回的结果),可以通过调用future对象的成员函数get()来获得。

    future:也有人称呼future提供了一个访问异步操作结果的机制,意思是这个结果你可能没有办法立马得到,在不久的将来,在现场执行完毕后,你就能拿到这个结果的,可以理解为,future对象会保存一个值,在将来的某个时刻能够拿到。

     1 #include <future>
     2 #include <thread>
     3 
     4 using namespace std;
     5 
     6 int mythread(){
     7     cout<<std::this_thread::get_id()<<endl;
     8     std::chrono::milliseconds dura(5000);//定义了5秒
     9     std::this_thread::sleep_for(dura);//休息了5秒
    10     return 5;
    11 }
    12 int main(){
    13     cout << "main" << this_thread::get_id() <<endl;
    14     std::future<int> result = std::async(mythread);//创建了一个线程,同thread类似,第一个参数是线程函数,第二个参数是对象引用,第三个之后的是线程函数的参数
    15     cout<<"continue..."<<endl;
    16     int def;
    17     def=0;
    18     cout<<result.get()<<endl;//系统执行到这里会卡到这儿等待子线程,等线程返回5后,继续向下走
    19                             //只能调用一次,在调用get就会出错
    20     //result.wait();等待线程返回本身不返回结果
    21     cout<<"main over"<<endl;
    22     return 0;
    23     
    24 }


    还可以在最前面添加一个参数,该参数类型是std::lunch类型(枚举类型),来达到一些特殊目的;
    延迟调用,并且没有创建新线程,是在主线程中调用的线程入口函数
    std::launch::deferred:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用才执行。
    如果wait或get没有被调用,那么线程就根本就没执行也没创建。
    std::future<int> result = std::async(std::lunch::deferred,mythread);

    前面还有一个参数,是默认的std::launch::async,在调用async函数的时候就创建线程了。

    std::packaged_task

    打包任务,把任务包装起来。

    是个类模板,模板参数是各种可调用对象,通过这个函数把这种可调用对象包转起来,方便将来作为线程入口函数来调用

     1 #include <future>
     2 #include <thread>
     3 
     4 using namespace std;
     5 
     6 int mythread(int& pt){
     7     cout << pt << endl;
     8     return 0;
     9 }
    10 int main(){
    11     //写法一:
    12     std::packaged_task<int(int)> mypt(mythread);//把函数mythread通过packaged_task包装起来,int(int):第一个int表示线程函数返回类型,括号里的int是线程函数的参数类型
    13     std::thread t1(std::ref(mypt),1);//线程直接开始执行,第二个参数就是线程入口函数的参数
    14     t1.join();
    15     std::future<int> result = mypt.get_future();
    16     cout<<result.get()<<endl;
    17     return 0;
    18     
    19     //写法二:用lambda表达式
    20     //这个时候,上面的mythread函数就删掉,相当于将线程入口函数定义写到了这个lambda表达式里面了。
    21     std::packaged_task<int(int)> mypt([](int pt){
    22         cout << pt << endl;
    23         return 0;
    24     
    25     })
    26 }

    作用是:

    可以使用vector<std::packaged_task<int(int)> > mytask;//用一个容器来保存所有线程入口函数对象

    怎么往容器里面添加对象?

    std::packaged_task<int(int)> mypt(mythread);
    mytasks.push_back(std::move(mypt));//move之后,mypt就空了

    怎么取出来?

    std::packaged_task<int(int)> mypt2;
    auto iter = mytasks.begin();//假设此时这个vector里面只有一个对象
    myptr2 = std::move(*iter);//移动语义
    mytasks.erase(iter);
    std::future<int> result = myptr2.get_future();
    cout<<result.get()<<endl;

    std::promise,类模板

    在某个线程中给他赋值,然后可以在其他线程中把这个值取出来用。

     1 void mythread(std::promise<int>& tmp,int calc){
     2     //做一些列复杂操作
     3     int result = calc;//保存结果
     4     tmp.set_value(result);//结果保存到了tmp对象中
     5     return;
     6 }
     7 
     8 int main(){
     9     std::promise<int> myprom;//声明一个promise型对象,保存的值类型为int
    10     std::thread t1(mythread,std::ref(myprom),180);
    11     t1.join();
    12     
    13     //获取结果值
    14     std::future<int> ful = myprom.get_future();
    15     auto result = ful.get();//get只能调用一次
    16     cout<<result<<endl;
    17 }
  • 相关阅读:
    【oracle ocp知识点一】
    poj 3280 区间dp
    TextView划线 android
    Apple Watch 集成环信SDK
    Android中使用HttpClient实现HTTP通信效果
    js 数组操作大集合
    5.5二叉树的遍历
    oracle学习之路(二)------数组类型/记录类型的使用
    推荐系统个人理解(实践部分)
    openstack之虚拟机创建流程分析
  • 原文地址:https://www.cnblogs.com/pacino12134/p/11244545.html
Copyright © 2011-2022 走看看