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

tech2025-03-20  7

#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)