目录
std::async与std::future
其他
std::package_task
std::promise
Reference
浅论:我看有人写的浅论异步编程的文章实际上在干的是介绍多线程,这里刚好最近对异步编程有所兴趣:我们来看看几个C++11新加进来的一些异步编程关键字。
这里需要对线程编程有所概念了我们好方便阅读,所以简单的想看看本文请先对多线程有一个基本的了解。
我们的本篇文章的主角是:std::async
,std::future
和std::package_task
,std::promise
等。
std::async
与std::future
std::async - cppreference.com
std::future - cppreference.com
异步的前几个字母!也就是说,我们这里就会创建一个异步的线程!默认的,他封装了std::thread以及将线程派发和发起线程的线程之间的沟通的几个流程,从复杂的需要自行定义的类封装转向了使用几个简单的关键字就可以完成任务。
auto future_res = std::async(task, params); # 这里的auto就是对应的std::future
我们需要传递什么呢?传递需要被线程执行的函数和她所需要的参数!
我们接受什么呢?一个叫做std::future
的模板类!这样理解:我们的线程工作是需要时间的,我们的结果在发起异步的时候尚无,但是我们预留了位置给线程执行的结果(从未来来hhh),所以叫std::future
std::future
需要被实例化为函数返回的结果的类型。其中,我们的结果需要以方法.get
来获取!如果异步操作还没有结束,那么会在此等待异步操作的结束,并获取返回的结果。wait()只是在此等待异步操作的结束,并不能获得返回结果。wait_for()超时等待返回结果。
我们来看一个稍微复杂的例子
template<typename... Args> int fastFunc(Args... a) { return (... + a); } int main(){ auto res = std::async(fastFunc<int, int, int>, 1, 2, 3); std::cout << res.get(); }
我们的函数流是这样执行的,
也就是说,我们总是可以保证在.get调用处拿到函数执行的结果!
async实际上有两种执行flag:仔细想想:你要不一发起就执行异步线程,要不等到你需要get的时候才执行:
std::launch::deferred
:设置了deferred标志,则async将进行惰性求值,即在async返回的std::future调用get函数时,将在当前线程(不一定是调用async时的线程)进行求值。std::launch::async
:设置了async标志,则async在新的线程执行函数f。(默认的是这个)
我们的async也为此设置了等待流程:比如说如果我们的线程执行超时了,我们应该如何处理:我们可以通过future_status去查询future的三种状态,分别是deferred(还未执行),ready(已经完成),timeout(执行超时),所以我们可以通过这个去查询异步操作的状态。使用这三种状态就OK!
template<typename... Args> int slowFunc(int sleepTime, Args... a){ std::this_thread::sleep_for(std::chrono::seconds(sleepTime)); return (... + a); } int main() { auto sleepTime = 5; // 假设的耗时时间 auto waitTime = 3; // 我们决定等待的时间 auto wait_for = std::async(slowFunc<int, int>, sleepTime, 1, 2); switch (wait_for.wait_for(std::chrono::seconds(waitTime))) { case std::future_status::ready: // 执行完事了! std::cout << "For this case, the waiting is enough!:>\n" << wait_for.get(); break; case std::future_status::deferred: // 设置了std::launch::deferred std::cout << "For your set! the func depatched!:>\n" << wait_for.get(); break; case std::future_status::timeout: // 执行超时了! std::cout << "Shit bro! the task timeout!:>\n " << wait_for.get(); break; default: break; } }
其他
我们可以认为std::async
是零散的由:std::future
和std::packaged_task
,std::promise
等类
std::package_task
std::packaged_task - cppreference.com
std::packaged_task
是一个类模板,顾名思义是用来打包的,将一个可调用对象封装起来,然后可以将其的返回值传给future。std::packaged_task<函数返回类型(参数类型)>
变量名(函数名)。
这个打包起来的任务要是想获得给我们所用的等待体,调用get_future
方法先接受,之后塞到线程里执行就可以。
std::promise
std::promise - cppreference.com
std::promise是一个类模板,它的作用是在不同的线程中实现数据的同步,与future结合使用,也间接实现了future在不同线程间的同步。他与future是结合使用的。(future和promise相互关联)
#include <iostream> #include <future> #include <thread> int fun(int x, std::promise<int>& p) { x++; x *= 10; p.set_value(x); std::cout << std::this_thread::get_id() << std::endl; return x; } int main() { std::promise<int> p; std::future<int> fu = p.get_future(); // 并将结果返回给future std::thread t(fun, 1, std::ref(p)); std::cout << fu.get() << std::endl; // 当promise还没有值的时候在此等待 std::cout << std::this_thread::get_id() << std::endl; t.join(); return 0; }
Reference
C++11异步编程(std::async, std::future, std::packaged_task, std::promise)-腾讯云开发者社区-腾讯云 (tencent.com)
C++11中std::async的使用详解_std::sync-CSDN博客
std::thread- cppreference.com