如果我们想要异步获取线程处理结果,可以使用future与async。async返回一个future对象,等待线程可以在future对象上获取异步线程的处理值。这里的异步,实际上主线程会阻塞。
【一】future的状态
future有三种状态:
std::future_status::deferred; //表示异步线程还未启动
std::future_status::ready; //表示异步线程已经执行完毕,并已经将执行结果写入到future中
std::future_status::timeout; // 表示异步线程处理超时,并没有将结果写入future中
【二】async是否启动线程
async是否启动异步线程,有async第一个参数决定,async接口定义如下:
async(std::launch::async | std::launch::deferred, f, args...)
第一个参数表示异步线程启动的方式,有如下两种方式:
std::launch::async; // 表示表用async函数后,立即启动异步线程
std::launch::deferred; // 表示线程延迟启动,当调用future.get或者future.wait时,才会创建异步线程并启动
而async的默认方式见接口所示:
std::launch::async | std::launch::deferred // 表示是否启动线程由系统负载决定,如果系统负载过重,则可能不启动异步线程计算,则此时future的状态不会为ready, 一般情况下,这种默认设置够用了,但是如果需要一定以异步线程的方式执行,则显示修改启动方式为async
【三】future的四个方法
future<int> fu;
fu.get();
get声明如下:
返回future中存取的int值,get在拿到数据之前,会一直阻塞
fu.wait();
wait声明如下:
没有返回值,一直等待,直到future状态为ready为止
fu.wait_for();
wait_for声明如下:
等待一定的时间,返回值为future的状态,如果等待超时,返回time_out
fu.wait_until();就是等待到某个时间点,与wait_for类似。
【四】async采用默认启动参数
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;
int f(int i)
{
cout << "start" << endl;
cout << "this thread id = " << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);
cout << "end" << endl;
return i;
}
int main(int argc, int * argv[])
{
future<int> fu = std::async(f, 8);
cout << fu.get() << endl;
cout << "main thread id = " << std::this_thread::get_id() << endl;
cout << "main" << endl;
system("pause");
}
结果如下:
可以看出,这里线程id不一样。
【五】先wait,后get
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;
int f(int i)
{
cout << "start" << endl;
cout << "this thread id = " << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);
cout << "end" << endl;
return i;
}
int main(int argc, int * argv[])
{
future<int> fu = std::async(f, 8);
fu.wait();
cout << fu.get() << endl;
cout << "main thread id = " << std::this_thread::get_id() << endl;
cout << "main" << endl;
system("pause");
}
结果如下:
【六】等待超时
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;
int f(int i)
{
cout << "start" << endl;
cout << "this thread id = " << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);
cout << "end" << endl;
return i;
}
int main(int argc, int * argv[])
{
future<int> fu = std::async(f, 8);
if (fu.wait_for(1s) == std::future_status::timeout) {
cout << "time out" << endl;
}
else {
cout << fu.get() << endl;
}
cout << "main thread id = " << std::this_thread::get_id() << endl;
cout << "main" << endl;
system("pause");
}
结果如下:
如果超时了还get,则会继续等待,直到future状态为ready,然后取出数据
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;
int f(int i)
{
cout << "start" << endl;
cout << "this thread id = " << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);
cout << "end" << endl;
return i;
}
int main(int argc, int * argv[])
{
future<int> fu = std::async(f, 8);
if (fu.wait_for(1s) == std::future_status::timeout) {
cout << "time out" << endl;
}
// 超时继续get
cout << fu.get() << endl;
cout << "main thread id = " << std::this_thread::get_id() << endl;
cout << "main" << endl;
system("pause");
}
结果如下:
【七】设置aysnc启动方式
#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>
#include<future>
#include<chrono>
using namespace std;
int f(int i)
{
cout << "start" << endl;
cout << "this thread id = " << std::this_thread::get_id() << endl;
std::this_thread::sleep_for(2s);
cout << "end" << endl;
return i;
}
int main(int argc, int * argv[])
{
// 设置启动方式为async
future<int> fu = std::async(std::launch::async,f, 8);
if (fu.wait_for(1s) == std::future_status::timeout) {
cout << "time out" << endl;
}
cout << fu.get() << endl;
cout << "main thread id = " << std::this_thread::get_id() << endl;
cout << "main" << endl;
system("pause");
}
结果如下: