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是一个模版类,是对于结果的封装:

  1. 在使用的时候,先实例化一个指定结果的primise对象。
  2. 通过promise对象,获取关联的future对象。
  3. 在任意位置给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;
}

在这里插入图片描述

  同理,依旧需要对不同作用域进行考虑,所以使用智能指针还是比较安全的,这里就不再赘述。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/7481.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++探索之路】STL---string

走进C的世界&#xff0c;也意味着我们对编程世界的认知达到另一个维度&#xff0c;如果你学习过C语言&#xff0c;那你绝对会有不一般的收获&#xff0c;感受到C所带来的码云风暴~ ---------------------------------------begin--------------------------------------- 什么是…

CF 339A.Helpful Maths(Java实现)

题目分析 输入一串式子&#xff0c;输出从小到大排列的式子 思路分析 如上所说核心思路&#xff0c;但是我要使用笨方法&#xff0c;输入一串式子用split分割开&#xff0c;但是此时需要用到转义字符&#xff0c;即函数内参数不能直接使用“”&#xff0c;而是“\\”。分割开后…

C#,入门教程(07)——软件项目的源文件与目录结构

上一篇&#xff1a; C#&#xff0c;入门教程(06)——解决方案资源管理器&#xff0c;代码文件与文件夹的管理工具https://blog.csdn.net/beijinghorn/article/details/124895033 创建新的 C# 项目后&#xff0c; Visual Studio 会自动创建一系列的目录与文件。 程序员后面的工…

Cpp::静态 动态的类型转换全解析(36)

文章目录 前言一、C语言中的类型转换二、为什么C会有四种类型转换&#xff1f;内置类型 -> 自定义类型自定义类型 -> 内置类型自定义类型 -> 自定义类型隐式类型转换的坑 三、C强制类型转换static_castreinterpret_castconst_castdynamic_cast 四、RTTI总结 前言 Hell…

Android中Service在新进程中的启动流程

目录 1、Service与AMS交互框架介绍 1.1、认识AMS代表IActivityManager 1.2、认识客户端代表IApplicationThread 2、Service启动流程概览 我们知道Android有四大组件&#xff0c;Activity、Service、ContentProvider、Broadcast&#xff0c;每个组件在系统运行中或者我们编写…

docker 简要笔记

文章目录 一、前提内容1、docker 环境准备2、docker-compose 环境准备3、流程说明 二、打包 docker 镜像1、基础镜像2、国内镜像源3、基础的dockerfile4、打包镜像 四、构建运行1、docker 部分2、docker-compose 部分2.1、构建docker-compose.yml2.1.1、同目录构建2.1.2、利用镜…

利用Redis实现数据缓存

目录 1 为啥要缓存捏&#xff1f; 2 基本流程&#xff08;以查询商铺信息为例&#xff09; 3 实现数据库与缓存双写一致 3.1 内存淘汰 3.2 超时剔除&#xff08;半自动&#xff09; 3.3 主动更新&#xff08;手动&#xff09; 3.3.1 双写方案 3.3.2 读写穿透方案 3.3.…

活动回顾和预告|微软开发者社区 Code Without Barriers 上海站首场活动成功举办!

Code Without Barriers 上海活动回顾 Code Without Barriers&#xff1a;AI & DATA 深入探索人工智能与数据如何变革行业 2025年1月16日&#xff0c;微软开发者社区 Code Without Barriers &#xff08;CWB&#xff09;携手 She Rewires 她原力在大中华区的首场活动“AI &…

python爬虫入门(一) - requests库与re库,一个简单的爬虫程序

目录 web请求与requests库 1. web请求 1.1 客户端渲染与服务端渲染 1.2 抓包 1.3 HTTP状态代码 2. requests库 2.1 requests模块的下载 2.2 发送请求头与请求参数 2.3 GET请求与POST请求 GET请求的例子&#xff1a; POST请求的例子&#xff1a; 3. 案例&#xff1a;…

全连接神经网络(前馈神经网络)

目录 一、初步认识全连接神经网络 1、神经元 2、网络结构 3、正向传播算法 二、反向传播算法 1、理解 2、迭代流程 三、构建神经网络模型的基本步骤 四、线性回归神经网络结构 4.1 数据处理 1、数据导入 2、数据归一化处理 3、数据集划分 4、数据形状变换 4.2 模…

【C++初阶】第11课—vector

文章目录 1. 认识vector2. vector的遍历3. vector的构造4. vector常用的接口5. vector的容量6. vector的元素访问7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模拟实现vector11. 迭代器失效11.1 insert插入数据内部迭代器失效11.2 insert插入…

Linux查看服务器的内外网地址

目录&#xff1a; 1、内网地址2、外网地址3、ping时显示地址与真实不一致 1、内网地址 ifconfig2、外网地址 curl ifconfig.me3、ping时显示地址与真实不一致 原因是dns缓存导致的&#xff0c;ping这种方法也是不准确的&#xff0c;有弊端不建议使用&#xff0c;只适用于测试…

PAT甲级-1024 Palindromic Number

题目 题目大意 一个非回文数&#xff0c;加上它的翻转数所得的和&#xff0c;进行k次&#xff0c;有可能会得到一个回文数。给出一个数n&#xff0c;限制相加次数为k次&#xff0c;如果小于k次就得到回文数&#xff0c;那么输出该回文数和相加的次数&#xff1b;如果进行k次还…

xss靶场

xss-labs下载地址&#xff1a;GitHub - do0dl3/xss-labs: xss 跨站漏洞平台 xss常见触发标签&#xff1a;XSS跨站脚本攻击实例与防御策略-CSDN博客 level-1 首先查看网页的源代码发现get传参的name的值test插入了html里头&#xff0c;还回显了payload的长度。 <!DOCTYPE …

数据结构——实验七·排序

欢迎各位大佬们来到Tubishu的博客&#x1f31f; Tubishu是一名计算机本科生&#xff0c;不定期发送一些在学校的成果供佬们消遣~希望能为佬的编程之路添砖加瓦⭐&#x1f525; 求各位大佬们垂怜&#x1f525;点赞评论一下呗&#x1f525;&#x1f525; 本文专栏 ➡️ 数据结构 …

使用vscode + Roo Code (prev. Roo Cline)+DeepSeek-R1使用一句话需求做了个实验

摘要 使用vscode、Roo Code和deepseek-reasoner进行了一个实验&#xff0c;尝试使用一句话需求来生成小红书封面图片。工具根据需求提供了详细的架构方案&#xff0c;包括技术栈选择、核心模块划分、目录结构建议等。然后&#xff0c;工具自动化地完成了开发和测试&#xff0c;…

vscode环境中用仓颉语言开发时调出覆盖率的方法

在vscode中仓颉语言想得到在idea中利用junit和jacoco的覆盖率&#xff0c;需要如下几个步骤&#xff1a; 1.在vscode中搭建仓颉语言开发环境&#xff1b; 2.在源代码中右键运行[cangjie]coverage. 思路1&#xff1a;编写了测试代码的情况&#xff08;包管理工具&#xff09; …

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…

積分方程與簡單的泛函分析8.具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程

1)def求解具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程 设 是定义在上的连续对称核函数&#xff0c; 非齐次第二类弗雷德霍姆积分算子方程的形式为&#xff1a; &#xff0c; 其中是未知函数&#xff0c;是给定的连续函数&#xff0c;是参数。 2)def其特徵值是否一致…

RV1126画面质量四:GOP改善画质

一&#xff0e; 什么是 GOP GOP 实际上就是两个 I 帧的间隔&#xff0c;比方说分辨率是 1920 * 1080 50 帧&#xff0c;假设 GOP 为 5&#xff0c;那就是大概 2s 插入一个 I 帧。我们再 回顾下&#xff0c;H264/H265 的帧结构。H264/H265 分别分为三种帧类型&#xff1a;I 帧、…