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 的核心能力可以概括为以下几个方面:…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...

C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...