关于CPP——std::future异步操作

目录

一、std::future 简介

1.1 概念

1.2 应用场景

1.3 关联的方法

1.3.1 std::async

1.3.2 std::package

1.3.3 std::promise

二、future 用法

2.1 使用std::async关联异步任务

2.2 使用std::packaged_task

1. 获取任务结果的机制:

2. 异步任务的管理:

3. 任务与执行环境分离:

4. 线程池和异步任务组合使用:

2.3 使用std::promise


一、std::future 简介

1.1 概念

std::future是C++11标准库中的⼀个模板类,它表示⼀个异步操作的结果。当我们在多线程编程中使⽤异步任务时,std::future可以帮助我们在需要的时候获取任务的执行结果。std::future的⼀个重要特性是能够阻塞当前线程,直到异步操作完成,从⽽确保我们在获取结果时不会遇到未完成的操作。

1.2 应用场景

  1. 异步任务:当我们需要在后台执⾏⼀些耗时操作时,如网络请求或计算密集型任务等,std::future 可以用来表示这些异步任务的结果。通过将任务与主线程分离,我们可以实现任务的并行处理,从而提⾼程序的执⾏效率
  2. 并发控制:在多线程编程中,我们可能需要等待某些任务完成后才能继续执⾏其他操作。通过使⽤std::future,我们可以实现线程之间的同步,确保任务完成后再获取结果并继续执⾏后续操作
  3. 结果获取:std::future提供了⼀种安全的⽅式来获取异步任务的结果。我们可以使用std::future::get() 函数来获取任务的结果,此函数会阻塞当前线程,直到异步操作完成。这样,在调用 get() 函数时,我们可以确保已经获取到了所需的结果

1.3 关联的方法

1.3.1 std::async

std::async 是一个函数模板:它会根据用户设置的传入参数选择不同的方案,异步执行一个函数,返回一个 future 对象用于获取函数结果。

1.3.2 std::package

std::packaged_task 是一个类模板:为一个函数生成一个异步任务对象,用于在其他线程中执行。是对函数的二次封装。

1.3.3 std::promise

std::promise 是一个类模板:实例化的对象可以返回一个 future ,在其他线程中向 promise 对象设置数据,其他线程的关联 future 就可以获取数据。是对结果的封装。

二、future 用法

2.1 使用std::async关联异步任务

 std::async 是⼀种将任务与 std::future 关联的简单⽅法。它创建并运行⼀个异步任务,并返回⼀个与该任务结果关联的 std::future 对象。
默认情况下, std::async 是否启动⼀个新线程,或者在等待 future 时,任务是否同步运行都取决于你给的参数。
这个参数为 std::launch 类型,以下介绍关于 std::launch 的三种策略:

std::launch::async 策略

  • 这个策略会立即启动一个新线程来执行异步任务。任务的执行是非阻塞的,意味着你可以在等待任务完成的同时继续执行其他代码。
  • 当你调用 future.get() 时,如果任务还未完成,程序会阻塞,直到异步任务完成并返回结果。

std::launch::deferred 策略

  • 这个策略不会立即创建线程执行任务,而是将任务推迟到你调用 future.get() 时才执行。换句话说,任务的执行是懒加载的方式,只有在你需要结果时,才会真正开始执行任务。
  • 在此模式下,任务的执行是同步的,意味着在你调用 get() 时任务才会运行,且在运行结束之前程序会被阻塞。因此,在调用 get() 之前不会创建新线程,所有任务都在调用 get() 的线程中完成。

std::launch::async | std::launch::deferred 策略

  • 内部通过系统等条件⾃动选择策略


#include <iostream>
#include <future>int Add(int num1, int num2)
{return num1 + num2;
}int main()
{// std::launch::async策略:内部创建一个线程执行函数,函数运行结果通过future获取// std::launch::deferred策略:同步策略,获取结果的时候再去执行任务std::future<int> res = std::async(std::launch::deferred, Add, 11, 22); // 进行了一个异步非阻塞调用// std::future<int>::get()  用于获取异步任务的结果,如果还没有结果就会阻塞std::cout << res.get() << std::endl;return 0;
}

2.2 使用std::packaged_task

std::packaged_task就是将任务和 std::feature 绑定在⼀起的模板,是⼀种对任务的封装。
我们可以通过 std::packaged_task 对象获取任务相关联的 std::future 对象,通过调用 get_future() 方法获得。

总结下来使用 std::packaged_task 的步骤就是:

1. 使用 package_task 封装需要异步操作的方法,可以使用 shared_ptr 进一步封装方便管理生命周期

auto task = std::make_shared < std::packaged_task < 返回值 ( 传入参数 ) > > ( 函数名 ) ;

2. 使用 future 模板获取 package_task 关联的 future 对象

std::future < 返回值类型res = task -> get_future() ;

3. 创建新线程执行异步操作的函数

4. 使用 future 的 get() 方法获取函数执行的结果

res.get()

#include <iostream>
#include <future>
#include <thread>
#include <memory>int Add(int num1, int num2)
{return num1 + num2;
}int main()
{// 1. 封装任务auto task = std::make_shared<std::packaged_task<int(int, int)>>(Add);// 2. 获取任务包关联的future对象std::future<int> res = task->get_future();std::thread thr([task](){ (*task)(11, 22); });// 3. 获取结果std::cout << res.get() << std::endl;thr.join();return 0;
}

观察了以上代码,你可能会有疑问,既然使用 future 与 package_task 也要新创建线程,那么为什么不直接创建新线程执行回调函数呢?下面会解答这个疑问:

使用 std::packaged_taskstd::future 的主要目的是为任务的结果获取机制提供更方便的方式,尤其是在任务和结果分离的场景下,而不仅仅是启动一个线程。这与直接使用 std::thread 的方式相比,有以下几个关键优势:

1. 获取任务结果的机制

  • std::packaged_task 会将一个任务(函数)与 std::future 绑定在一起,因此你可以通过 future.get() 来获取任务的执行结果。
  • 当你只使用 std::thread 时,线程完成的任务结果必须通过其他方式传递,比如共享状态、回调函数等,这些方式通常更复杂且容易出错。而 std::future 提供了一个更安全和简单的接口。

2. 异步任务的管理

  • 使用 std::future 可以轻松等待异步任务完成,通过调用 future.get() 可以阻塞当前线程,直到任务完成并返回结果。而使用 std::thread 时,没有一个简单的方法来阻塞线程并获取任务结果,必须自己处理同步机制。
  • std::future 提供了一种更标准化的机制来处理任务的执行和结果获取,这使得代码的可读性和可维护性更好。

3. 任务与执行环境分离

  • std::packaged_taskstd::future 将任务(Add 函数)与它的执行环境(线程)解耦。你可以在任何时候启动任务并获取结果,而不必担心线程的创建和管理。这为任务调度提供了更大的灵活性,比如可以通过不同的方式执行任务:立即执行、推迟执行或在线程池中执行。
  • 直接使用 std::thread 需要你手动管理线程的生命周期,比如什么时候开始、什么时候结束、如何获取结果等。

4. 线程池和异步任务组合使用

  • 在一些场景下,你可能会将任务提交到一个线程池中,而不是直接创建线程。在这种情况下,使用 std::packaged_taskstd::future 可以非常方便地处理任务的提交和结果获取,而不需要手动管理线程的创建和销毁。
  • 例如,你可以将 std::packaged_task 提交给线程池,而 future 则用来等待并获取任务的结果。

2.3 使用std::promise

在使用 promise 时,先实例化一个 promise 对象,然后实例化 future 对象接收 promise 对象关联的 future 对象,这样就实现了 promise 与 future 的绑定,然后后续通过对 promise 对象做修改, future 对象就可以获得异步操作函数的返回值  

#include <iostream>
#include <future>
#include <thread>
#include <memory>int Add(int num1, int num2)
{return num1 + num2;
}int main()
{//   1. 在使用的时候,就是先实例化一个指定结果的promise对象,std::promise<int> pro;//   2. 通过promise对象,获取关联的future对象std::future<int> res = pro.get_future();//   3. 在任意位置给promise设置数据,就可以通过关联的future获取到这个设置的数据了std::thread thr([&pro](){int sum = Add(11 , 22);pro.set_value(sum); });std::cout << res.get() << std::endl;thr.join();return 0;  
}

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

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

相关文章

Qt/C++开源项目 TCP客户端调试助手(源码分享+发布链接下载)

这是一个TCP客户端调试助手&#xff0c;具有简洁直观的界面&#xff0c;用户能够方便地测试TCP协议的通信功能&#xff0c;并可同时作为客户端与服务器端使用。以下是该程序的功能特点及用途介绍&#xff1a; 功能特点&#xff1a; TCP客户端与服务器调试&#xff1a;支持同时…

【word导出带图片】使用docxtemplater导出word,通知书形式的word

一、demo-导出的的 二、代码操作 1、页面呈现 项目要求&#xff0c;所以页面和导出来的word模版一致 2、js代码【直接展示点击导出的js代码】 使用插件【先下载这五个插件&#xff0c;然后页面引入插件】 import docxtemplater from docxtemplater import PizZip from pizzip …

LTE PSS主同步信号搜索 MATLAB实现

本期带来PSS相关检测说明和MATLAB实现&#xff0c;本期只讲相关方面的&#xff0c;所以MATLAB实现也是相关的部分&#xff0c;频偏估计方面的待下期开讲。 LTE 4G PSS搜索分为TDD搜索和FDD搜索&#xff0c;但是对于 TDD 和 FDD 而言&#xff0c;PSS同步信号的结构是完全一样的&…

sheng的学习笔记-AI-半监督聚类

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 半监督学习&#xff1a;sheng的学习笔记-AI-半监督学习-CSDN博客 聚类&#xff1a;sheng的学习笔记-AI-聚类(Clustering)-CSDN博客 均值算法&#xff1a;sheng的学习笔记-AI-K均值算法_k均值算法怎么算迭代两次后的最大…

图形验证码从设计到实现

验证码的使用场景 图形验证码在我们的日常使用中是非常常见的&#xff0c;比如一些App、小程序、PC网站等。涉及到的业务也比较广泛、例如用户登录流程、注册流程、找回密码。下面我们来大致梳理下上述流程&#xff1a; 登录流程 用户首先在登录界面输入手机号然后通过图形验…

VMware时提示系统尚未修改安装失败

安装VMware安装失败&#xff0c;提示系统尚未修改 有以下解决方案&#xff1a; 1.操作系统不兼容 2.安装文件损坏 3.安装程序错误 4.硬件问题 解决&#xff1a;由于重装系统前&#xff0c;安装过VAware&#xff0c;所以应该操作系统&#xff0c;硬件没有问题。下载一个软件v…

关于Redis集群同步/持久化/淘汰机制的详解

Redis是非常常用的KV数据库, 使用内存以及HashMap进行存储的特点带来了高效的查询. 本文将围绕Redis的常见开发使用场景, 阐述在Redis集群中各个节点是如何进行数据同步, 每个节点如何进行持久化以及在长期使用中如何对数据进行更新和淘汰. 如果对Redis有更多的兴趣, 可以查看我…

Java中方法的使用详解

1.引言 假设有一个美女博主&#xff0c;每次发的照片都特别漂亮 然后该博主的评论区每次都会有很多粉丝的评论&#xff1a; 哇&#xff01;宝宝好漂亮&#xff0c;求上衣链接&#xff01;&#xff01;&#xff01; 老婆亲亲&#xff01;这个口红是什么色号呀&#xff1f; 宝…

【go】内存分配模型

内存是怎么分配给对象的&#xff1f; 内存分配优化的地方是&#xff1f; 讲讲golang内存分配模型&#xff1f; ans: 1.按照对象的大小分配&#xff1a;先算出对象的大小如果是tiny对象&#xff0c;就从tiny block中获取地址和偏移量&#xff0c;将对象打包到mcache;如果是16B以…

Python 在Excel中应用和取消多种不同类型的数据筛选

目录 安装Python Excel处理库 Python 在 Excel 中应用文本筛选 Python 在 Excel 中应用数字筛选 Python 在 Excel 中应用字体颜色、单元格颜色或图标集筛选 Python 在 Excel 中应用日期筛选 Python 在 Excel 中应用动态日期筛选 Python 在 Excel 中筛选空单元格或非空单…

【ArcGIS Pro第一期】界面简介

ArcGIS Pro简介 ArcGIS Pro界面简介1.1 打开工程1.2 使用功能区上的工具 参考 ArcGIS Pro 是一种基于功能区的应用程序。 ArcGIS Pro 窗口顶部的功能区有许多命令可供选择&#xff0c;而根据需要打开的各个窗格&#xff08;可停靠窗口&#xff09;中则提供了更为高级或专用的功…

快速排序(QuickSort)-归并排序(MergeSort)[java编写]

1. 快速排序 1.1 基本概述 快速排序采用分治思想&#xff0c;即在一个无序的序列中选取一个任意的基准元素pivot&#xff0c;利用pivot 将待排序的序列分成两部分&#xff0c;前面部分元素均小于或等于基准元素&#xff0c;后面部分均大于或等于基准元素&#xff0c;然后采用…

参会邀请 | 第二届机器视觉、图像处理与影像技术国际会议(MVIPIT 2024)

第二届机器视觉、图像处理与影像技术国际会议&#xff08;MVIPIT 2024&#xff09;将于2024年9月13日-15日在中国张家口召开。 MVIPIT 2024聚焦机器视觉、图像处理与影像技术&#xff0c;旨在为专家、学者和研究人员提供一个国际平台&#xff0c;分享研究成果&#xff0c;讨论…

算法训练营——day3长度最小子数组

1 长度最小子数组-力扣209&#xff08;中等&#xff09; 1.1 题目&#xff1a; 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返…

基于orangePi的智能家居系统

目录 一.接线图 1.orangePi接线 2.继电器接线 二.语音模块的配置 1.pin脚的配置 2.命令词自定义信息 三.测试 1.通过gpio指令测试烟雾检测器是否正确连接 2.编写脚本测试其他模组接线是否正常 四.人脸识别方案 1.首先开通人脸搜索识别服务 2. 点击产品控制台,向人…

2024年四川省安全员B证证考试题库及四川省安全员B证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年四川省安全员B证证考试题库及四川省安全员B证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大…

ARM----时钟

时钟频率可以是由晶振提供的&#xff0c;我们需要高频率&#xff0c;但是外部接高的晶振会不稳定&#xff0c;所有使用PLL&#xff08;锁相环&#xff09;来放大频率。接下来就让我们学习用外部晶振提供的频率来配置时钟频率。 一.时钟源的选择 在这里我们选择外部晶振作为时钟…

数据库面试题学习

B树和B树 B树 排好序的 节点内部有多个元素 B树 排好序的 节点内多个元素 叶子节点有指针&#xff08;双向指针&#xff09; 非叶子节点冗余了一份在叶子节点 mysql定义B树 InnoDB B树是B树的升级版~ InnoDB b树是怎么产生的 mysql 页 目录 16KB 自增id uuid 一页最多可以存储…

【精选】文件摆渡系统:跨网文件传输的安全与效率之选

文件摆渡系统可以解决哪些问题&#xff1f; 文件摆渡系统&#xff08;File Shuttle System&#xff09;主要是应用于不同网络、网段、区域之间的文件数据传输流转场景&#xff0c; 用于解决以下几类问题&#xff1a; 文件传输问题&#xff1a; 大文件传输&#xff1a;系统可…