一、std::async,std::future创建后台任务并返回值
- std::async 是个函数模板,用来启动一个异步任务,启动之后, 返回一个std::future对象;
- std::future是个类模板(异步任务:就是自动创建一个线程并开始执行对应的入口函数,它返回一个std::future 对象(线程返回结果),我们可以通过调用future对象成员函数get()来获取结果)
- std::future 提供了一种访问异步操作结果的机制
- std::future 的 get() 函数,等待线程运行结束,拿到结果 ,只能调用一次,不能调用多次
#include <mutex>
#include <future>
using namespace std;
//线程入口函数
int MyThread()
{
cout << "MyThread Start " << "thread id = " << std::this_thread::get_id() << endl;
this_thread::sleep_for(std::chrono::milliseconds(5000)); //线程休息5秒
cout << "MyThread End " << "thread id = " << this_thread::get_id() << endl;
return 5;
}
int main()
{
cout << "main thread id" << this_thread::get_id() << endl;
future<int> result = std::async(MyThread); //创建一个线程并开始执行,流程并不会卡到这里
//也可以用类的成员函数作为线程让你口函数
//Test obj;
//future<int> result = std::async(&Test::MyThread, &obj,25); //默认第一个参数是调用std::launch::async
cout << "contine..." << endl;
cout << result.get() << endl; //卡在这里等待MyThread()执行完毕,拿到结果
//result.wait() 等待线程返回,本身并不会返回结果
cout << "I Love China" << endl;
return 0;
}
- future 里面的 wait()函数:等待线程返回,本身并不会返回结果。
- 通过额外向std::async()传递一个参数,该参数是std::lunnch类型(枚举类型)。
6.1 std::lannch::deferred : 表示线程入口函数调用被延迟到std::future的wait()或者get()函数调用时才执行;此时如果没有调用wait()或者get()函数,线程就根本不会创建,线程函数就不会被调用。
6.2 std::lannch::deferred : 延迟调用,并没有创建新线程(线程ID一样),是在主线程中调用的入口函数。
Test obj;
future<int> result = std::async(std::launch::deferred,&Test::MyThread, &obj,25);
6.3 在调用async函数的时候就开始创建线程,不传参数时,默认值是:std::launch::async | std::launch::deferred两者合二为一,系统会自行决定是异步(创建新线程)还是同步(不创建新线程)方式运行
Test obj;
future<int> result = std::async(std::launch::async,&Test::MyThread, &obj,25);
二、std::packged_task 打包任务
- std::packged_task: 是个类模板,它的模板参数是各种调用对象,方便将来作为线程入口函数
重要代码部分:
//int(int) 代表是线程入口函数的参数和返回值
std::packaged_task<int(int)> myPt(MyThread); //将线程入口函数包装起来
std::thread obj(std::ref(myPt), 2); //线程开始执行
obj.join();
std::future<int> result = myPt.get_future(); //std::future对象里面有线程入口函数的返回结果,这里result保存返回的结果
完整代码演示:
//线程入口函数
int MyThread(int num)
{
cout << num << endl;
cout << "MyThread Start " << "thread id = " << std::this_thread::get_id() << endl;
this_thread::sleep_for(std::chrono::milliseconds(5000)); //线程休息5秒
cout << "MyThread End " << "thread id = " << this_thread::get_id() << endl;
return 5;
}
int main()
{
cout << "main thread id = " << this_thread::get_id() << endl;
std::packaged_task<int(int)> myPt(MyThread); //将线程入口函数包装起来
std::thread obj(std::ref(myPt), 2); //线程开始执行
obj.join();
std::future<int> result = myPt.get_future(); //std::future对象里面有线程入口函数的返回结果,这里result保存返回的结果
cout << result.get() << endl;
cout << "I Love China" << endl;
return 0;
}
也可以用lambd表达式作为可调用对象
int main()
{
std::packaged_task<int(int)> mypt([](int pair) {
cout << pair << endl;
cout << "MyThread Start " << "thread id = " << std::this_thread::get_id() << endl;
this_thread::sleep_for(std::chrono::milliseconds(5000)); //线程休息5秒
cout << "MyThread End " << "thread id = " << this_thread::get_id() << endl;
return 5;
});
std::thread obj(std::ref(mypt), 2); //线程开始执行
obj.join();
//mypt(10) //也可以直接调用 但是这种是不会创建新的线程
std::future<int> result = mypt.get_future(); //std::future对象里面有线程入口函数的返回结果,这里result保存返回的结果
cout << result.get() << endl;
cout << "I Love China" << endl;
return 0;
}
三、std::promise 类模板
1.作用:能在某个线程中给它赋值,然后可以在其他线程中把值取出来使用
//线程入口函数
void MyThread(std::promise<int> &temp,int calc)
{
//做一些列的运算
calc++;
calc *= 10;
//其他计算,比如花费了5秒中
std::this_thread::sleep_for(std::chrono::milliseconds(5000));
//保存结果
temp.set_value(calc);
}
void MyThread1(std::future<int> &temp)
{
auto result = temp.get();
cout << "Result = " << result << endl;
}
int main()
{
std::promise<int> promise; //声明一个std::promise对象,保存的值类型为int
thread obj(MyThread, std::ref(promise), 10);
obj.join();
//获取结果值
future<int> result = promise.get_future();
thread obj1(MyThread1, std::ref(result)); //重新创建一个线程,将计算的结果给另外一个线程使用
obj1.join();
//auto value = result.get(); //get()只能调用一次
//cout << "result = " << value << endl;
return 0;
}