头文件 #include<future> ,在Linux下需要添加 -lpthread 参数
std::async
本质上是创建一个线程,使用传递的任务方法在线程中运行, 通过std::launch::async/deferred 来设置是否立即调用还是延迟调用
std::future
获得任务结果, 使用future的get方法,获得任务执行的返回值, 但是如果当前任务尚未执行, 任务会触发立即执行, 并且堵塞当前线程,直到任务完成
方法
- get() //获取任务返回结果,该方法只能调用一次, 使用后futrue变得不确定
- wait() //等待任务完成
- wait_for(dur) //等待一定时间或运行完成
- wait_until(fp) //等待某一时刻或运行完成
- share() //生成一个shared_future,shared_futrue类型允许使用第二次, 并且使用获得结果与第一次一样,如果有一场,抛出的异常也是一样的。
* 范例1
#include <iostream>
#include <future>
int main(int argc, char* args[])
{
//创建完成后线程实际上已经开始运行
std::future<int> ret = std::async([](){
std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
//假设这里是一个很费时间的一个操作
return 0;
});
std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
//如果当前任务未完成的话,主线程会堵塞,当然我们也可以把堵塞的任务传递给其他线程做
std::cout << "Ret:" << ret.get() << std::endl;
return 0;
}
* 范例2
多线程下的使用
#include <iostream>
#include <future>
//任务方法
void task(std::promise<int> &prom)
{
int ret;
//假设这里是一个很费时间的一个操作
ret = 4;
prom.set_value_at_thread_exit(ret);
}
//打印任务结果
void printRet(std::future<int> &future)
{
std::cout << "ret:" << future.get() << std::endl;
}
int main(int argc, char* args[])
{
std::promise<int> prom;
std::future<int> future = prom.get_future();
//创建线程执行任务
std::thread t = std::thread(task, std::ref(prom));
//创建线程接受任务执行结果
std::thread t2 = std::thread(printRet, std::ref(future));
//等待线程完成
t.join();
t2.join();
return 0;
}
* 范例3
参数传递
#include <iostream>
#include <future>
int sum(int a, int b)
{
return a + b;
}
int main(int argc, char* args[])
{
//创建完成后线程实际上已经开始运行,参数附加在末尾
std::future<int> ret = std::async(sum, 1, 2);
std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
//如果当前任务未完成的话,主线程会堵塞,当然我们也可以把堵塞的任务传递给其他线程做
std::cout << "Ret:" << ret.get() << std::endl;
return 0;
}
std::shared_future
使用与futrue相似。,shared_futrue类型允许使用第二次, 并且使用获得结果与第一次一样,如果有一场,抛出的异常也是一样的
std::shared_futrue f = std::async(task).share();
std::packaged_task(重点)
将任务打包, 好处是,可以手动触发何时执行任务
#include <iostream>
#include <future>
int sum(int a, int b)
{
std::cout << "Task Thread ID:" << std::this_thread::get_id() << std::endl;
return a + b;
}
int main(int argc, char* args[])
{
//对任务进行封装
std::packaged_task<int(int, int)> task(sum);
//获取future
std::future<int> future = task.get_future();
//直接出发任务task(1, 2),但是任务处于调用线程中
//移动到线程中执行异步任务
std::thread t = std::thread(std::move(task), 1, 3);
std::cout << "Main Thread ID:" << std::this_thread::get_id() << std::endl;
std::cout << "Ret:" << future.get() << std::endl;
t.join();
return 0;
}
范例 4
使用wait_for 等待任务完成
#include <iostream>
#include <future>
double recursive(double a)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if ( a == 0)
{
return a;
}
return recursive(a - 1) + a;
}
int main()
{
std::packaged_task<double(double)> task(recursive);
std::future<double> future = task.get_future();
//移动到线程中处理
std::thread t = std::thread(std::move(task), 1000);
std::thread t2 = std::thread([](std::future<double>& future){
//等待线程完成执行
while (future.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout)
{
std::cout << ".";
}
std::cout << "\n" << std::endl;
std::cout << "result:" << future.get() << std::endl;
}, std::ref(future));
t.join();
t2.join();
return 0;
}
范例 5
futrue共享状态在get调用后就解除,下次调用会发生报错。 但是使用shared_future的时候,get方法可调用多次,但是结果是一样的
#include <iostream>
#include <future>
int do_work()
{
return 100;
}
int main()
{
std::future<int> future = std::async(do_work);
//获取共享future
std::shared_future<int> shared_future = future.share();
//shared_future多次获取结果
std::cout << "ret1:" << shared_future.get() << std::endl;
std::cout << "ret2:" << shared_future.get() << std::endl;
return 0;
}