std::async
#include<future>
template<class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type> async(launch policy, Fn&& fn, Args&&...args);
该函数包含在头文件中。
当不着急要任务结果时,可以使用std::async启动一个异步任务。与std::thread对象等待的方式不同,std::async会返回一个std::future对象,这个对象持有最终计算出来的结果。当需要这个值时,只需要调用这个对象的get()成员函数;并且会阻塞线程直到期望值状态为就绪为止;之后,返回计算结果。
与std::thread 做的方式一样,std::async允许你通过添加额外的调用参数,向函数传递额外的参数。
看如下代码
#include <string>
#include <future>
struct X
{
void foo(int,std::string const&);
std::string bar(std::string const&);
};
X x;
auto f1=std::async(&X::foo,&x,42,"hello"); // 调用p->foo(42, "hello"),p是指向x的指针
auto f2=std::async(&X::bar,x,"goodbye"); // 调用tmpx.bar("goodbye"), tmpx是x的拷贝副本
struct Y
{
double operator()(double);
};
Y y;
auto f3=std::async(Y(),3.141); // 调用tmpy(3.141),tmpy通过Y的移动构造函数得到
auto f4=std::async(std::ref(y),2.718); // 调用y(2.718)
X baz(X&);
std::async(baz,std::ref(x)); // 调用baz(x)
class move_only
{
public:
move_only();
move_only(move_only&&)
move_only(move_only const&) = delete;
move_only& operator=(move_only&&);
move_only& operator=(move_only const&) = delete;
void operator()();
};
auto f5=std::async(move_only()); // 调用tmp(),tmp是通过std::move(move_only())构造得到
默认情况下,期望值是否等待取决于std::async是否启动一个线程,或是否有任务正在进行同步。大多数情况下会新产生线程去执行,也可以在函数调用之前向std::async传递一个额外参数,这个参数可以是std::launch::defered,表明函数调用被延迟到wait()或get()函数调用时才执行,也可以是std::launch::async 表明函数必须在其所在的独立线程上执行,std::launch::deferred | std::launch::async表明实现可以选择这两种方式的一种。最后一个选项是默认的,当函数调用被延迟,它可能不会再运行了。
下面是我们的测试代码
#include<iostream>
#include<future>
#include<thread>
#include<unistd.h>
#include<chrono>
void print()
{
sleep(3);
std::cout << "print\n";
}
void print2()
{
sleep(3);
std::cout << "print2\n";
}
int main(int argc, char *argv[])
{
std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
auto f = std::async(std::launch::async, print);
print2();
auto end = std::chrono::system_clock::now();
auto t = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
std::cout << "time = " << t << "\n";
std::cout << "hello\n";
}
我们用到了std::launch::async参数,让其异步的去开启线程执行。我们在主函数中先让async开启线程去执行函数print,然后在让主线程执行print1,如果是async是异步执行的,运行结果应该是3秒。
运行结果如下所示
发现真的是异步执行并且运行结果如我们期望的那样。
接着我又做了测试,将std::launch::async这个参数去掉,发现它也是异步执行的,执行结果和上图所示结果相同,这个就是系统决定的结果了,大部分情况下会分配线程去执行。
我又做了一个测试,现在我将函数改为如下所示,不添加期望值去等待。
std::async(std::launch::async, print);
看一下运行结果
运行结果就是顺序执行函数的结果,没有去将print函数在独立的线程去运行,所以想要异步的执行记得要用期望值去接收函数的返回值才能异步的去运行。
std::launch::deffered参数就是直到期望值调用get想要获取结果时才阻塞的等待线程处理,如果一直不调用get,async中添加的函数是一直不会执行的。
#include<iostream>
#include<future>
#include<thread>
#include<unistd.h>
#include<chrono>
void print()
{
sleep(3);
std::cout << "print\n";
}
void print2()
{
sleep(3);
std::cout << "print2\n";
}
int main(int argc, char *argv[])
{
//获取当前时间
std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
auto f = std::async(std::launch::defferred, print);
print2();
auto end = std::chrono::system_clock::now();
auto t = std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
std::cout << "time = " << t << "\n";
f.get();
auto end2 = std::chrono::system_clock::now();
t = std::chrono::duration_cast<std::chrono::seconds>(end2 - end).count();
std::cout << "time2 = " << t << "\n";
std::cout << "hello\n";
}
运行结果如下图所示
发现在调用get之前函数print一直没有运行。与上述结论相同。
博主最近开始才学习这些内容,如果有理解不对的希望可以在评论去指出!感谢!