C++11之std::future和std::promise
为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执行join(),过程相对繁琐。
thread库提供了future用来访问异步操作的结果。std::promise用来包装一个值将数据和future绑定起来,为获取线程函数中的某个值提供便利,取值是间接通过promise内部提供的future来获取的,也就是说promise的层次比future高。
#include "stdafx.h"
#include <iostream>
#include <type_traits>
#include <future>
#include <thread> using namespace std;
int main()
{
std::promise<int> promiseParam;
std::thread t([](std::promise<int>& p)
{
std::this_thread::sleep_for(std::chrono::seconds());// 线程睡眠10s
p.set_value_at_thread_exit();//
}, std::ref(promiseParam));
std::future<int> futureParam = promiseParam.get_future(); auto r = futureParam.get();// 线程外阻塞等待
std::cout << r << std::endl; return ;
}
上述程序执行到futureParam.get()时,有两个线程,新开的线程正在睡眠10s,而主线程正在等待新开线程的退出值,这个操作是阻塞的,也就是说std::future和std::promise某种程度也可以做为线程同步来使用。
std::packaged_task包装一个可调用对象的包装类(如function,lambda表达式(C++11之lambda表达式),将函数与future绑定起来。std::packaged_task与std::promise都有get_future()接口,但是std::packaged_task包装的是一个异步操作,而std::promise包装的是一个值。
#include "stdafx.h"
#include <iostream>
#include <type_traits>
#include <future>
#include <thread> using namespace std;
int main()
{
std::packaged_task<int()> task([]() {
std::this_thread::sleep_for(std::chrono::seconds());// 线程睡眠10s
return ; });
std::thread t1(std::ref(task));
std::future<int> f1 = task.get_future(); auto r = f1.get();// 线程外阻塞等待
std::cout << r << std::endl; return ;
}
而std::async比std::promise, std::packaged_task和std::thread更高一层,它可以直接用来创建异步的task,异步任务返回的结果也保存在future中。std::async的原型:
async( std::launch policy, Function&& f, Args&&... args );
std::launch policy有两个,一个是调用即创建线程(std::launch::async),一个是延迟加载方式创建线程(std::launch::deferred),当掉使用async时不创建线程,知道调用了future的get或者wait时才创建线程。之后是线程函数和线程参数。
#include "stdafx.h"
#include <iostream>
#include <future>
#include <thread> int main()
{
// future from a packaged_task
std::packaged_task<int()> task([]() {
std::cout << "packaged_task started" << std::endl;
return ; }); // wrap the function
std::future<int> f1 = task.get_future(); // get a future
std::thread(std::move(task)).detach(); // launch on a thread // future from an async()
std::future<int> f2 = std::async(std::launch::deferred, []() {
std::cout << "Async task started" << std::endl;
return ; }); // future from a promise
std::promise<int> p;
std::future<int> f3 = p.get_future();
std::thread([&p] { p.set_value_at_thread_exit(); }).detach(); f1.wait();
f2.wait();
f3.wait();
std::cout << "Done!\nResults are: "
<< f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
}
C++11之std::future和std::promise的更多相关文章
- C++11之std::future和std::promise和std::std::packaged_task
为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执 ...
- 【C++并发实战】(三) std::future和std::promise
std::future和std::promise std::future std::future期待一个返回,从一个异步调用的角度来说,future更像是执行函数的返回值,C++标准库使用std::f ...
- C++11 并发指南四(<future> 详解三 std::future & std::shared_future)
上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...
- C++并发编程之std::async(), std::future, std::promise, std::packaged_task
c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...
- C++11 并发指南四(<future> 详解三 std::future & std::shared_future)(转)
上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...
- C++ 11新特性:std::future & std::shared_future) (转载)
上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...
- C++11 使用异步编程std::async和std::future
先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...
- 第27课 “共享状态”及其管理者(std::future/std::shared_future)
一. “共享状态” (一)“共享状态”对象 1. 用于保存线程函数及其参数.返回值以及新线程状态等信息.该对象通常创建在堆上,由std::async.std::promise和std::package ...
- C++并发编程之std::future
简单地说,std::future 可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段.std::future 通常由某个 Provider 创建,你可以把 Provider 想象成 ...
随机推荐
- WCF IIS 部署错误处理
做Web接口,原来一直用Web Service的,但是.Net 3.5后,Web Service变成了WCF.代码的编写上,把WebMethod特性改成了OperationContract,然后把方法 ...
- Vue.js小案例(1)
数据绑定 数据绑定是vue.js的基础.本例中就是利用了vue.js的v-model指令在表单元素上创建双向数据绑定. <!--这是我们的View--> <div id=" ...
- MySQL数据库(9)----使用连接实现多表检索
有许多演示如何使用MySQL所支持的连接操作的示例,都用到了下列两个表 t1 和 t2: mysql> SELECT * FROM t1; +----+------+ | i1 | c1 | + ...
- Get a “step-by-step” evaluation in Mathematica
Is it possible in Mathematica to get a step-by-step evaluation of some functions; that's to say, out ...
- 在 ubuntu 上运行 php 脚本
在 ubuntu 上运行 php 脚本 一.配置运行环境 1.要在 ubuntu 上运行 php 脚本,需要安装 Apache2 和 PHP 具体步骤,请参考:Ubuntu 搭建Web服务器(MySQ ...
- Jmeter与LoadRunner的异同
1.jmeter的架构跟loadrunner原理一样,都是通过中间代理,监控&收集并发客户端发现的指令,把他们生成脚本,再发送到应用服务器,再监控服务器反馈的结果的一个过程. 2.分布式中间代 ...
- PHP后台处理jQuery Ajax跨域请求问题 — xx was not called解决办法
// 前台代码 $.ajax({ url: 'http://www.ushark.net/home/save_trial_apply', dataType: 'jsonp', processData: ...
- Linux内核 网络数据接收流程图
各层主要函数以及位置功能说明: 1)sock_read:初始化msghdr{}的结构类型变量msg,并且将需要接收的数据存放的地址传给msg.msg_iov->iov_base. ...
- XmlIgnore的使用
public class Group { public string GroupName; [XmlIgnore] public string Comments; } 在序列化时,其结果如下所示 &l ...
- Python学习---网络编程 1217【all】
OSI七层模型: 物理层, 数据链路层, 网络层,传输层,会话层,表达层,应用层 应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等 传输层:TCP,UDP 网络层:I ...