关键词
//都会返回一个std::future,用来提供执行结果
std::async、std::paclaged_task、std::promise
知识点
1、std::future<>()
:
a).std::future
的临时对象在调用析构函数
时会阻塞
当前线程。注意在局部区域内的std::future
的析构。
b).std::future::get()
和std::future::wait()
同样会阻塞当前线程。
2、std::async
:
a).当调用std::future::get()
会阻塞当前线程,知道得到结果。
b).当调用std::async(fun*)
时,未必会在新的线程中执行,若明确要在新线程中执行,可以使用std::launch::async
参数如:std::async(std::launch::async,func*)
;强制在新线程中执行。
3、std::pack_task
:
a).自身不定义函数,可以包装其他函数,可以配合在新的std::thread
中使用如下:
#include <iostream>
#include <future>
#include <thread>
//定义函数
auto fun = [](int value) {
std::this_thread::sleep_for(std::chrono::seconds(5));
//睡眠5s后返回结果
return 100 + value;
};
//创建仿函数(包装函数)
std::packaged_task<int(int)> pk_task{fun};
//定义仿函数返回值返回于何处
std::future<int> f = pk_task.get_future();
//配合线程正式调用,使用move来实现右值引用,后面跟``着需要的传参
std::thread t1(std::move(pk_task), 20);
int main(){
//获取结果参数
std::cout << f.get() << std::endl;
//确定thread的加入方式
t1.join();
}
b).调用仿函数的方式有两种:
1、显式调用(直接调用),如上定义了pk_task
伪函数,则可以:pk_task(10)
进行直接调用,而后使用std::future::get()
得到期值。
2).异步调用,如a)中一样,通过移动语句把pk_task(10)
的控制权交给新线程,并开始执行,但别忘了,线程需要join
或detach
,否则系统异常终止。
注意:执行pk_task
等价于执行fun(10)
3、std::promise
:
a).非常强大的机制。例如,你可以将一个值传递给新进程,而不需要任何额外的同步操作
b).具体作用就是许诺一个值,这个值时std::future
类型,可以用std::promise::get_future()
来许诺这个值,只有调用std::promise::set_value()
时这个承诺才会兑现,并且具体调std::promise::get_future()
的行为者才会执行。如下:
auto promissFun = [](std::future<int> fut) { std::this_thread::sleep_for(std::chrono::seconds(5)); //睡眠5s后返回结果 std::cout <<"ID: " << std::this_thread::get_id()<< std::endl; std::cout <<"get(): " << fut.get() << std::endl; };
std::promise<int> my_promise; std::thread t2(promissFun, my_promise.get_future());
//未调用std::future::set_value
//...进入promissFun函数中,执行到fut.get()时``会阻塞等待,直到set_value()设置
//调用std::future::set_value
my_promise.set_value(50);
//确定thread的加入方式
t2.join();
补充说明
标签:std,异步,task,编程,调用,C++,future,线程,promise From: https://www.cnblogs.com/lvshen/p/17869098.html