C++11中提供的异步任务高级抽象,包含在 < future>头文件中,它能让我们方便的实现异步地执行一个耗时任务,并在需要的时候获取其结果。
我举几个例子:
1.批量拷贝/下载文件;
2.进行一个复杂的计算;
3.执行多个嵌套的SQL查询语句;
在实际开发中,计算机进行这些操作的时候,都需要在一定时间后才能返回结果,这个时候就需要我们用异步。比起直接使用std::thread 相比,std::async和std::future有以下优势:
1.std::async 返回的future对象,可以方便地等待callable对象执行完成并获取其返回值;
2.能从实现库的一些高级功能中获益,比如线程池等,并大大减少异常的产生。
我们来看下实际代码例子future:
#include <iostream> #include <future> #include <chrono> bool is_prime(int x) { for(int i=2;i<x;i++) { if(x%i==0) return false; return true; } } int main() { std::future <bool> fut = std::async(is_prime,4444444444444444443); std::cout<<"wait,Checking"; std::chrono::milliseconds span(10); while(fut.wait_for(span)==std::future_status::timeout) std::cout<<'.'<<std::flush; bool x = fut.get(); std::cout<<"\n4444444444444444443"<<(x?" is":"is not") << " prime.\n"; return 0; }
std::future 可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段。std::future 通常由某个 Provider 创建,你可以把 Provider 想象成一个异步任务的提供者,Provider 在某个线程中设置共享状态的值,与该共享状态相关联的 std::future 对象调用 get(通常在另外一个线程中) 获取该值,如果共享状态的标志不为 ready,则调用 std::future::get 会阻塞当前的调用者,直到 Provider 设置了共享状态的值(此时共享状态的标志变为 ready),std::future::get 返回异步任务的值或异常(如果发生了异常)。
函数async()用法很像thread,同样可以启动一个线程,但该函数返回的是一个future对象而非thread对象,因此它的侧重点在于计算结果而非过程。接下来看下thread代码和async代码之间的转换:
#include <iostream> #include <thread> #include <future> using namespace std; int main(int argc, char const *argv[]) { thread t([]{cout<<"hello"<<endl;}); t.join(); return 0; }
上面的代码等同于:
#include <iostream> #include <thread> #include <future> using namespace std; int main(int argc, char const *argv[]) { auto f =async([]{cout<<"hello"<<endl;}); f.wait(); return 0; }