async,future,packaged_task,promise

张开发
2026/4/20 1:37:52 15 分钟阅读

分享文章

async,future,packaged_task,promise
一.std::asyncstd::future创建后台任务并返回值原来通过thread对象创建一个线程用成员函数join()等待程序完成现在希望线程返回一个结果可以把线程的结果赋给一个变量有一个更好的办法std::async。相关概念std::async是一个类模板用来启动一个异步任务之后它返回一个std::future的对象std::future是一个类模板。启动异步任务自动创建一个线程并开始执行对应的线程入口函数返回一个std::future的对象。这个std:future的对象里面就有线程入口函数所返回的结果。可以通过调用future对象成员函数get()来获取结果。一个future对象只能调用一次get()。future的另外一个成员函数wait()会等待线程返回但本身不返回结果。语法1.普通函数std::future数据类型 result(future对象名这里假设为result)std::async(入口函数名); std::coutresult.get()std::endl; //输出入口函数返回的结果线程会卡在get()这里等待入口函数执行完毕拿到返回值 //result.wait(); //等待线程返回本身不返回结果 //不用get()或者wait()不报错但仍然会等待线程执行完毕2.成员函数std::future数据类型 resultstd::async(类名,类对象名,传入参数); std::coutresult.get()std::endl;3.通过额外向std::async()传递一个参数该参数类型是std::lunnch类型枚举类型)来达到一些特殊的目的std::launch::deferred表示线程入口函数调用被延迟到std::future的wait或者get函数调用时才执行不会创建新线程而是在主线程中调用入口函数std::future数据类型 resultstd::async(launch::deferred,入口函数名); std::coutresult.get()std::endl;std::launch::async(默认标记)在调用async函数的时候就开始创建线程示例#includeiostream #includethread #includelist #includemutex #includefuture #includemap using namespace std; class A { public: int print(int val) { cout 线程print开始id this_thread::get_id() endl; this_thread::sleep_for(chrono::seconds(1)); //休息5秒 cout 线程print结束id this_thread::get_id() endl; return val; //返回值 } }; int print1() { cout 线程print1开始id this_thread::get_id() endl; this_thread::sleep_for(chrono::seconds(1)); //休息5秒 cout 线程print1结束id this_thread::get_id() endl; return 5; //返回值 } int main() { cout 主线程开始id this_thread::get_id() endl; futureint result async(print1); cout result.get() endl; //卡在这里等待print函数执行完拿到返回值 A a; int val 10; futureint result2 async(A::print,a,val); cout result2.get() endl; std::cout 主线程结束 std::endl; return 0; }二.std::packaged_task是一个类模板模板参数是各种可调用对象。作用通过std::packaged_task把各种可调用对象包装起来方便作为线程入口函数调用。语法std::packaged_task函数类型(传入函数的参数类型) 对象名1(入口函数); std::thread 对象名2(std::ref(对象名1),传入的参数); 对象名2.join(); std::future数据类型result对象名1.get_future(); std::coutresult.get()std::endl; //成员函数get_future()保存的是被包装的入口函数返回的值 //或(示例lambda表达式) std::packaged_taskint(int) p([](int val{函数定义})); int a; p(a); //相当于函数调用没有创建线程 std::futureintresultp.get_future(); std::coutresult.get()std::endl; //示例存入容器和取用 vectorstd::packaged_taskint(int) v; //容器 v.push_back(std::move(p)); //移动语义移动后p为空 auto itv.begin(); packaged_taskint(int) p2; //接收容器中的对象 p2std::move(*it);std::packaged_task是一个仅移动类型move-only它没有拷贝构造函数只有移动构造函数。如果不用std::ref编译器会尝试拷贝p导致编译错误;#includeiostream #includethread #includelist #includemutex #includefuture #includemap #includevector using namespace std; int print1(int val) { cout 线程print1开始id this_thread::get_id() endl; this_thread::sleep_for(chrono::seconds(1)); //休息5秒 cout 线程print1结束id this_thread::get_id() endl; return val; //返回值 } int main() { cout 主线程开始id this_thread::get_id() endl; packaged_taskint(int) p(print1); thread t1(ref(p), 1); t1.join(); futureintresult p.get_future(); //成员函数get_future()保存的是p里面的被包装的入口函数返回的值 cout result.get() endl; packaged_taskint(int) p1([](int val) { cout 线程print1开始id this_thread::get_id() endl; this_thread::sleep_for(chrono::seconds(1)); //休息5秒 cout 线程print1结束id this_thread::get_id() endl; return val; //返回值 }); p1(6); vectorpackaged_task int(int) v; //容器 v.push_back(std::move(p1)); //移动语义移动后p1为空 auto it v.begin(); packaged_taskint(int) p2; //接收容器中的对象 p2 std::move(*it); v.erase(it); futureintresult1 p2.get_future(); cout result1.get() endl; std::cout 主线程结束 std::endl; return 0; }三.std::promise作用在某个线程中给它赋值然后可以再其他线程中把这个值取出来用语法//函数示例 void cal(std::promiseinttemp,int a) { a*100; temp.set_value(a); //将计算结果存入temp对象 } void thread1(std::futureint temp) { auto result temp.get(); std::cout result std::endl; } int main() { std::promiseint mp; //声明一个promise对象 thread t(cal,std::ref(mp),10); t.join(); std::futureintfmp.get_future(); thread t2(thread1, std::ref(f)); //将结果传入t2 t2.join(); cout主线程结束std::endl; return 0; }

更多文章