1、async和future的使用
(1)std::async std::future创建后台任务并返回
【1】std::async
std::async是一个函数模板,用来启动一个异步任务,启动起来就是一个已步入任务后,返回一个std::future 对象,std::future是一个类模板
“启动一个异步任务”,就是创建一个线程并执行对应线程的入口函数,返回一个std::future对象
std::future对象内含有线程入口函数所返回的结果(线程返回结果)。我们可以通过调用对象的成员函数get()类获取结果
std::future提供一种访问异步操作结果的机制,就是说你不能立马拿到结果,需要等待线程结束的时候,你就能拿到结果
【2】std::packaged_task: 打包任务
是一个类模板,他的模板参数是各种可调用对象,通过std::packaged_task把各种可调用对象包装起来,方便将来作为线程入口;
packaged_task包装起来的可调用对象还可以直接调用
【3】std::promise,类模板
在某个线程中给他赋值,然后在其他的线程中,把这个值取出来
示例一:std::async 与 std::future的使用
// 程序通过std::future对象的get()成员函数,等待线程执行结束并返回结果,没拿到返回值,程序不会往下运行
// wait()成员函数等待线程返回,不返回结果
std::future<int> res = std::async(ThreadIO, 2); // 创建一个线程开始执行
cout << "continue ... " << endl;
int def = 0;
cout << res.get() << endl; // 卡在这里等待threasIO执行完
// res.wait(); //不会有返回值
cout << "end" << endl;
(2)std::async()的其他参数
通过std::async()传递一个参数,此参数类型是std::lunnch(枚举类型),来实现其他的函数功能
【1】std::launch::deferred:表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行
如果wait()或者get()没有被调用,线程不会被创建,所以线程不会执行
【2】std::launch::async,在调用async函数的时候就开始创建线程
std::async()函数默认的就是std::launch::async参数
示例二:std::lunnch使用用例
threadIO thIO;
int tmppar = 12;
cout << "main thread ID " << this_thread::get_id() << endl;
std::future<int> res = std::async(&threadIO::ThreadIO, &thIO, tmppar); // 正常使用
//std::future<int> res = std::async(std::launch::deferred, &threadIO::ThreadIO, &thIO, tmppar);
//std::future<int> res = std::async(std::launch::async, &threadIO::ThreadIO, &thIO, tmppar);
cout << "continue ... " << endl;
int def = 0;
cout << res.get() << endl; // 卡在这里等待threasIO执行完
// res.wait();
(3)打包函数
packaged_task使用用例
cout << "main thread ID " << this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(ThreadIO);
std::thread t1(std::ref(mypt), 1); // 创建线程,线程直接开始执行,第二份参数作为线程入口函数的参数
t1.join();
std::future<int> res = mypt.get_future(); // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
cout << res.get() << endl;
cout << "end" << endl;
打包lumda表达式
std::packaged_task<int(int)> mypt([](int num) {
cout << "input thread param " << num << endl;
cout << "start this thread ID " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "end this thread ID " << std::this_thread::get_id() << endl;
return 5;
});
代码示例
#include <iostream>
#include <thread>
#include <mutex>
#include <future>
#include <vector>
using namespace std;
int ThreadIO(int num)
{
cout << "input thread param " << num << endl;
cout << "start this thread ID " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "end this thread ID " << std::this_thread::get_id() << endl;
return 5;
}
void promiseThread(std::promise<int> &temp, int num)
{
num += 10;
int res = num;
temp.set_value(res); // 将结果保存到temp对象中
}
void proThread(std::future<int> &temp)
{
auto res = temp.get();
cout << "proThread res: " << res << endl;
return;
}
int main()
{
/* // 示例一 :打包函数
cout << "main thread ID " << this_thread::get_id() << endl;
std::packaged_task<int(int)> mypt(ThreadIO);
std::thread t1(std::ref(mypt), 1); // 创建线程,线程直接开始执行,第二份参数作为线程入口函数的参数
t1.join();
std::future<int> res = mypt.get_future(); // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
cout << res.get() << endl;
cout << "end" << endl;
*/
// 示例二 : 打包lumda表达式
std::packaged_task<int(int)> mypt([](int num) {
cout << "input thread param " << num << endl;
cout << "start this thread ID " << std::this_thread::get_id() << endl;
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
cout << "end this thread ID " << std::this_thread::get_id() << endl;
return 5;
});
#if 0 // 容器的用法
std::vector<packaged_task<int(int)>> vProj;
vProj.push_back(std::move(mypt));
std::packaged_task<int(int)> mypt2;
auto it = vProj.begin();
mypt2 = std::move(*it); // 移动语义
vProj.erase(it); // 删除第一个元素,后续不能使用it
mypt2(520);
std::future<int> res1 = mypt2.get_future(); // 获取线程返回值,std::future对象里包含有线程入口函数的返回结果
cout << res1.get() << endl;
cout << "end" << endl;
#endif
std::promise<int> tPromise; // 声明promise对象,保存类型为int
std::thread t(promiseThread, std::ref(tPromise), 180);
t.join();
// 获取结果
std::future<int> ful = tPromise.get_future(); // 拿到上一个线程的值
//auto res = ful.get();
//cout << res << endl;
std::thread t1(proThread, std::ref(ful)); // get()不能重复调用,在proThread()函数中有调用,所以上面需要注释掉
t1.join();
cout << "end" << endl;
system("pause");
return 0;
}