C++异步future
🌎 C++11异步futrue
文章目录:
C++11异步futrue
future介绍
应用场景
future操作
std::async函数模版
std::packaged_task类模版
std::promise类模版
🚀future介绍
std::future是C++11标准库中的⼀个模板类,它表⽰⼀个异步操作的结果。当我们在多线程编程中使⽤异步任务时,std::future可以帮助我们在需要的时候获取任务的执⾏结果。std::future的⼀个重要特性是能够阻塞当前线程,直到异步操作完成,从⽽确保我们在获取结果时不会遇到未完成的操作。
🚀应用场景
- 异步任务: 当我们需要在后台执⾏⼀些耗时操作时,如⽹络请求或计算密集型任务等,std::future可以⽤来表⽰这些异步任务的结果。通过将任务与主线程分离,我们可以实现任务的并⾏处理,从⽽提⾼程序的执⾏效率。
- 并发控制: 在多线程编程中,我们可能需要等待某些任务完成后才能继续执⾏其他操作。通过使⽤std::future,我们可以实现线程之间的同步,确保任务完成后再获取结果并继续执⾏后续操作。
- 结果获取:std::future提供了⼀种安全的⽅式来获取异步任务的结果。我们可以使⽤std::future::get()函数来获取任务的结果,此函数会阻塞当前线程,直到异步操作完成。这样,在调⽤get()函数时,我们可以确保已经获取到了所需的结果。
🚀future操作
一个main thread可以顺序执行多个IO操作,但是执行IO操作是非常耗费时间的,而我们又恰好只是想要IO操作的结果,所以main thread就可以通过创建child thread来执行IO,再通过future来获取IO结果:

std::future本质上不是一个异步任务,而是一个辅助我们获取异步任务结果的东西。

std::future并不能单独使用,必须搭配一些能够执行异步任务的模版类或函数一起使用,异步任务使用搭配:
- std::async函数模版:异步执行一个函数,返回函数对象,获取函数执行结果。
- std::packaged_task类模版:为一个函数生成一个异步任务对象(可调用对象),用于在其他线程中执行。
- std::promise类模版:实例化的对象可以返回一个future,在其他线程中向promise对象设置数据,其他线程的关联future就可以获取数据。
🚩std::async函数模版
std::async是⼀种 将任务与std::future关联 的简单⽅法。它创建并运⾏⼀个异步任务,并返回⼀个与该任务结果关联的std::future对象。默认情况下,std::async是否启动⼀个新线程,或者在等待future时,任务是否同步运⾏都取决于你给的 参数。这个参数为std::launch类型:
- std::launch::deferred:表明该函数会被延迟调⽤,直到在future上调⽤get()或者wait()才会开始执⾏任务。
- std::launch::async: 表明函数会在⾃⼰创建的线程上运⾏。
- std::launch::deferred | std::launch::async: 内部通过系统等条件⾃动选择策略。
#include <iostream>
#include <future>int Add(int num1, int num2)
{std::cout << "into Add()!" << std::endl;return num1 + num2;
}int main()
{// std::launch::async策略:内部创建一个线程执行函数,函数运行结果通过future获取// std::launch::deferred策略:同步策略,获取结果的时候再去执行任务// std::future<int> res = std::async(std::launch::async, Add, 11, 22);// 进行了一个异步非阻塞调用,调用后直接执行std::future<int> res = std::async(std::launch::deferred, Add, 11, 22);// 进行同步调用,调用后等待wait或get才会执行std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "——————————————————————————————————" << std::endl;// std::future<int>::get() : 用于获取异步任务的结果,如果还没有结果就会阻塞std::cout << res.get() << std::endl;return 0;
}

🚩std::packaged_task类模版
std::packaged_task就是将任务和 std::feature 绑定在⼀起的模板,是⼀种对任务的封装。我们可以通过std::packaged_task对象获取任务相关联的std::feature对象,通过调⽤ get_future() 方法获得。std::packaged_task的模板参数是函数签名。可以把std::future和std::async看成是分开的,⽽ std::packaged_task则是⼀个整体。
std::async是一个模版函数,内部会创建线程执行异步任务,而std::packaged_task是一个模版类,一个任务包,是对一个函数进行二次封装,封装成为一个可调用对象作为任务放到其他线程执行的。任务包封装好了以后,可以在任意位置进行调用,通过关联的future来获取执行结果。
#include <iostream>
#include <future>
#include <thread>int Add(int num1, int num2)
{std::cout << "into Add()!" << std::endl;return num1 + num2;
}int main()
{// 1. 封装任务std::packaged_task<int(int, int)> task(Add);// 封装成task任务包// 2. 获取任务包关联的future对象std::future<int> res = task.get_future();// 2. 执行任务task(11, 22);// 3. 获取结果std::cout << res.get() << std::endl;return 0;
}

这是在main thread中执行task,但是我们想要的是可以异步执行任务,所以创建一个线程来进行异步执行任务。
尽量不要把任务函数当成线程的入口函数,这样每次执行任务创建线程,任务结束线程也会销毁,如果任务过于调用频繁会导致线程不断的创建销毁。比较好的方式是把任务放在线程池当中让去不断的执行任务。
创建线程,以匿名函数作为线程的入口函数,内部再调用task任务包,单但是lambda表达式不能直接传task(调用拷贝构造)。
因为std::packaged_task不允许拷贝构造,所以我们可以通过传递指针的方式防止拷贝构造发生。同时task如果在不同作用域,需要考虑作用域的问题(res获取不到get_future),不能直接传裸的指针,可以通过智能指针进行管理并传参。
#include <iostream>
#include <future>
#include <thread>
#include <memory>int Add(int num1, int num2)
{std::cout << "into Add()!" << std::endl;return num1 + num2;
}int main()
{// 1. 封装任务auto task = std::make_shared<std::packaged_task<int(int, int)>>(Add);// 封装成task任务包, 创建智能指针进行管理// 2. 获取任务包关联的future对象std::future<int> res = task->get_future();std::thread trd([task](){ // 匿名函数作为线程入口函数,让线程来执行封装后的任务(*task)(11, 22);});// 3. 获取结果std::cout << res.get() << std::endl;trd.join();return 0;
}

🚩std::promise类模版
std::promise提供了⼀种设置值的⽅式,它可以在设置之后通过相关联的std::future对象进⾏读取。换种说法就是之前说过std::future可以读取⼀个异步函数的返回值, 但是要等待就绪, ⽽std::promise就提供⼀种方式⼿动让 std::future就绪。
std::promise是一个模版类,是对于结果的封装:
- 在使用的时候,先实例化一个指定结果的primise对象。
- 通过promise对象,获取关联的future对象。
- 在任意位置给promise设置数据,就可以通过关联的future获取到这个设置的数据。
#include <iostream>
#include <thread>
#include <future>
#include <memory>int Add(int num1, int num2)
{std::cout << "into Add()!" << std::endl;return num1 + num2;
}int main()
{// 1. 在使用的时候,先实例化一个指定结果的primise对象。std::promise<int> pro;// 2. 通过promise对象,获取关联的future对象。std::future<int> ret = pro.get_future();// 3. 在任意位置给promise设置数据,就可以通过关联的future获取到这个设置的数据。std::thread td([&pro](){int sum = Add(11, 22);pro.set_value(sum);});std::cout << ret.get() << std::endl;td.join();return 0;
}

同理,依旧需要对不同作用域进行考虑,所以使用智能指针还是比较安全的,这里就不再赘述。
相关文章:
C++异步future
🌎 C11异步futrue 文章目录: C11异步futrue future介绍 应用场景 future操作 std::async函数模版 std::packaged_task类模版 std::promise类模版 🚀future介绍 std::future是C11标准库…...
Oracle 12c 中的 CDB和PDB的启动和关闭
一、简介 Oracle 12c引入了多租户架构,允许一个容器数据库(Container Database, CDB)托管多个独立的可插拔数据库(Pluggable Database, PDB)。本文档旨在详细描述如何启动和关闭CDB及PDB。 二、容器数据库 (CDB) 2.1…...
Vue组件开发-使用 html2canvas 和 jspdf 库实现PDF文件导出 设置页面大小及方向
在 Vue 项目中实现导出 PDF 文件、调整文件页面大小和页面方向的功能,使用 html2canvas 将 HTML 内容转换为图片,再使用 jspdf 把图片添加到 PDF 文件中。以下是详细的实现步骤和代码示例: 步骤 1:安装依赖 首先,在项…...
chrome插件:网页图片高清下载
前置条件: 安装有chrome谷歌浏览器的电脑 使用步骤: 1.打开chrome扩展插件 2.点击管理扩展程序 3.加载已解压的扩展程序 4.选择对应文件夹 5.成功后会出现一个扩展小程序 6.点击对应小程序 7.输入需要访问的网址,点击扩展插件即可进行图片…...
汽车定速巡航
配备定速巡航功能的车型,一般在方向盘附近设有4~6个按键(可能共用键位)。 要设置定速巡航,不仅需要方向盘上的按键,还要油门配合。 设置的一般流程: 开关:类似步枪上的“保险”,按…...
CNN-BiLSTM卷积双向长短期记忆神经网络时间序列预测(Matlab完整源码和数据)
CNN-BiLSTM卷积双向长短期记忆神经网络时间序列预测(Matlab完整源码和数据) 目录 CNN-BiLSTM卷积双向长短期记忆神经网络时间序列预测(Matlab完整源码和数据)预测效果基本介绍 CNN-BiLSTM卷积双向长短期记忆神经网络时间序列预测一…...
WPF基础 | WPF 布局系统深度剖析:从 Grid 到 StackPanel
WPF基础 | WPF 布局系统深度剖析:从 Grid 到 StackPanel 一、前言二、Grid 布局:万能的布局王者2.1 Grid 布局基础:构建网格世界2.2 子元素定位与跨行列:布局的精细操控2.3 自适应布局:灵活应变的秘诀 三、StackPanel…...
14-6-2C++STL的list
(一)list对象的带参数构造 1.list(elem);//构造函数将n个elem拷贝给本身 #include <iostream> #include <list> using namespace std; int main() { list<int> lst(3,7); list<int>::iterator it; for(itlst.begi…...
【AI论文】Sigma:对查询、键和值进行差分缩放,以实现高效语言模型
摘要:我们推出了Sigma,这是一个专为系统领域设计的高效大型语言模型,其独特之处在于采用了包括DiffQKV注意力机制在内的新型架构,并在我们精心收集的系统领域数据上进行了预训练。DiffQKV注意力机制通过根据查询(Q&…...
私域流量池构建与转化策略:以开源链动2+1模式AI智能名片S2B2C商城小程序为例
摘要:随着互联网技术的快速发展,流量已成为企业竞争的关键资源。私域流量池,作为提升用户转化率和增强用户粘性的有效手段,正逐渐受到企业的广泛关注。本文旨在深入探讨私域流量池构建的目的、优势及其在实际应用中的策略…...
vofa++使用方法
控件区可以添加控件用来啊多样显示 点击一个控件然后右键可以选择要添加显示的数据,点all表全部显示, 点auto可以自动布局 要用控件需要选择协议,不知道协议具体格式可以点击问号看看,并且最好用printf重定义来实现 比如我要实现F…...
LogicFlow 一款流程图编辑框架
LogicFlow是什么 LogicFlow是一款流程图编辑框架,提供了一系列流程图交互、编辑所必需的功能和灵活的节点自定义、插件等拓展机制。LogicFlow支持前端自定义开发各种逻辑编排场景,如流程图、ER图、BPMN流程等。在工作审批流配置、机器人逻辑编排、无代码…...
HTML<kbd>标签
例子 在文档中将一些文本定义为键盘输入: <p>Press <kbd>Ctrl</kbd> <kbd>C</kbd> to copy text (Windows).</p> <p>Press <kbd>Cmd</kbd> <kbd>C</kbd> to copy text (Mac OS).</p>…...
PyQt6医疗多模态大语言模型(MLLM)实用系统框架构建初探(上.文章部分)
一、引言 1.1 研究背景与意义 在数字化时代,医疗行业正经历着深刻的变革,智能化技术的应用为其带来了前所未有的发展机遇。随着医疗数据的指数级增长,传统的医疗诊断和治疗方式逐渐难以满足现代医疗的需求。据统计,全球医疗数据量预计每年以 48% 的速度增长,到 2025 年将…...
150 Linux 网络编程6 ,从socket 到 epoll整理。listen函数参数再研究
一 . 只能被一个client 链接 socket例子 此例子用于socket 例子, 该例子只能用于一个客户端连接server。 不能用于多个client 连接 server socket_server_support_one_clientconnect.c /* 此例子用于socket 例子, 该例子只能用于一个客户端连接server。…...
深入浅出 SQLSugar:快速掌握高效 .NET ORM 框架
SQLSugar 是一个高效、易用的 .NET ORM 框架,支持多种数据库(如 SQL Server、MySQL、PostgreSQL 等)。它提供了丰富的功能,包括 CRUD 操作、事务管理、动态表名、多表联查等,开发者可以通过简单的链式操作实现复杂的数…...
ESP8266 NodeMCU与WS2812灯带:实现多种花样变换
在现代电子创意项目中,LED灯带的应用已经变得极为广泛。通过结合ESP8266 NodeMCU的强大处理能力和FastLED库的高效功能,我们可以轻松实现多达100种灯带变换效果。本文将详细介绍如何使用Arduino IDE编程,实现从基础到高级的灯光效果ÿ…...
MacOS安装Docker battery-historian
文章目录 需求安装battery-historian实测配置国内源相关文章 需求 分析Android电池耗电情况、唤醒、doze状态等都要用battery-historian, 在 MacOS 上安装 battery-historian,可以使用 Docker 进行安装runcare/battery-historian:latest。装完不需要做任…...
Linux的基本指令(上)
1.ls指令 语法:ls [选项] [目录或文件] 功能:对于⽬录,该命令列出该⽬录下的所有⼦⽬录与⽂件。对于⽂件,将列出⽂件名以及其他信息。 常用选项: -a 列出⽬录下的所有⽂件,包括以 . 开头的隐含⽂件。 -d 将…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.1 从零搭建NumPy环境:安装指南与初体验
1. 从零搭建NumPy环境:安装指南与初体验 NumPy核心能力图解(架构图) NumPy 是 Python 中用于科学计算的核心库,它提供了高效的多维数组对象以及用于处理这些数组的各种操作。NumPy 的核心能力可以概括为以下几个方面:…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
