std::async、std::future
- 启动一个异步任务(),返回一个std::future类模板对象,可以使用get函数获取结果。如果不需要返回值,可以使用std::future对象的wait函数。
注意:有时候async并不创建线程,std::launch::async强制异步任务创建线程,std::launch::deferred并不创建线程,这是async于thread的最大不同。 - get函数只能调用一次,且会一直阻塞到拿到返回值为止。
- 给std::async传入std::launch类型参数,默认参数为std::launch::async|std::launch::deferred。std::launch::deferred可以延迟启动线程。直到调用wait或者get再启动,启动后没有创建新线程,而是直接在主线程中调用线程函数。
- std::future还有其他的wait_for,wait_until函数。返回一个枚举类型std::future_status。
- std::future可以使用valid()函数判断
- std::launch::async|std::launch::deferred,参数表示async的行为从两者中选择,由系统自行选择。
int mythread(){
std::chrono::milliseconds dura(5000);
std::this_thread::sleep_for(dura);
return 0;
}
int main()
{
std::future<int> result = std::async(std::launch::async,mythread);
std::future_status status = result.wait_for(std::chrono::seconds(6));
if(status == std::future_status::ready)
{
//线程执行完
resutl.get();
}
else if(status == std::future_status::timeout)
{
//线程还没执行完,等待时间已经用完
}
else if(status == std::future_status::deferred)
{
//线程还没启动,此时传入的是std::launch::deferred
}
return 0;
}
std::shared_future
对于std::future,get函数的设计是移动语义,只能get一次。再次调用会报异常。
std::shared_future也是一个类模板。get函数复制结果。多个线程都可以get。
std::shared_future对象的使用
std::future result = std::async...
std::shared_future shared_result(std::move(result));
std::shared_future shared_result(result.share());//执行完毕,result空了
也可以直接使用get_future返回值强行转换。
std::packaged_task
类模板,模板参数是各种可调用对象。通过packaged_task包装成线程入口函数。所以packaged_task也是一个可调用对象。
std::string getDataFromDB(std::string token) {
//获取数据
std::string data = "Data fetched from DB by Filter :: " + token;
return data;
}
int main() {
//创建封装回调函数的packaged_task<>
std::packaged_task<std::string(std::string)> task(getDataFromDB);
//从packaged_task<>获取相关的future<>
std::future<std::string> result = task.get_future();
//将packaged_task传递给线程以异步运行
std::thread th(std::move(task), "Arg");
//join线程,阻塞直到线程完成时返回
th.join();
//获取packaged_task<>的结果,即getDataFromDB()的返回值
std::string data = result.get();
std::cout << data << std::endl;
return 0;
}
std::promise
在一个线程中赋值,在另一个线程中取出来。
总结:通过promise保存一个值,在将来某个时刻把future绑定到promise上来得到绑定的值。可以将获取的future传入到其他线程,再调用get。
void mythread(std::promise<int > &tmpp, int data)
{
//todo
data++;
tmpp.set_value(data);
}
int main()
{
std::promise<int > myprom;
std::thread t1(mythread,std::ref(myprom),180);
t1.join();
//promise和future绑定,用于获取返回值
std::future<int> fur = myprom.get_future();
auto result = fur.get();
return 0;
}