【仿RabbitMQ消息队列】基于C++11中packaged_tack异步线程池
目录
什么是同步和异步?
future
使用future和async配合管理异步任务
使用promise和future配合管理异步任务
使⽤std::packaged_task和std::future配合
C++11异步线程池
什么是同步和异步?
同步(Synchronous)
同步编程是指程序按照代码的顺序,一步步执行,每一步必须等待上一步执行完毕,才能执行下一步。在同步操作中,如果某个任务(如I/O操作、网络请求等)需要等待(比如等待磁盘读写完成、等待网络响应等),程序就会阻塞在那里,直到该任务完成,才能继续执行后续的代码。这种方式简单直观,但效率较低,尤其是在处理需要长时间等待的任务时,会导致程序响应变慢或“假死”。
异步(Asynchronous)
异步编程则允许程序在等待某个长时间运行的操作(如文件I/O、网络请求等)完成时,继续执行后续的代码,而不会阻塞当前线程。当异步操作完成时,通常通过回调函数、Promises、Future、async/await等方式来通知程序,以便执行后续依赖于该操作结果的操作。这种方式可以提高程序的效率和响应性,尤其是在处理多个并发任务时。
future
介绍
std::future是C++11标准库中的⼀个模板类,它表⽰⼀个异步操作的结果。当我们在多线程编程中使⽤异步任务时,std::future可以帮助我们在需要的时候获取任务的执⾏结果。std::future的⼀个重要特性是能够阻塞当前线程,直到异步操作完成,从⽽确保我们在获取结果时不会遇到未完成的操作。
简单来说:future就是可以用来获取一个异步任务/函数的结果的;
应用场景:
- 异步任务: 当我们需要在后台执⾏⼀些耗时操作时,如⽹络请求或计算密集型任务等,std::future可以⽤来表⽰这些异步任务的结果。通过将任务与主线程分离,我们可以实现任务的并⾏处理,从⽽提⾼程序的执⾏效率
- 并发控制: 在多线程编程中,我们可能需要等待某些任务完成后才能继续执⾏其他操作。通过使⽤std::future,我们可以实现线程之间的同步,确保任务完成后再获取结果并继续执⾏后续操作
- 结果获取:std::future提供了⼀种安全的⽅式来获取异步任务的结果。我们可以使⽤std::future::get()函数来获取任务的结果,此函数会阻塞当前线程,直到异步操作完成。这样,在调⽤get()函数时,我们可以确保已经获取到了所需的结果
使用future和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 <thread>
#include <future>
#include<chrono>
using namespace std;
int Add(int num1, int num2)
{cout << "加法" << endl;return num1 + num2;
}
int main()
{// 两个版本// 函数+不定参数// 策略+函数+不定餐cout<<"first "<<endl;//deferred: 在执行get获取异步结果的时候才会执行异步任务//async: 内部会创建工作线程异步完成任务future<int> result = async(std::launch::deferred, Add, 11, 22);// 返回值是什么参数就是什么std::this_thread::sleep_for(chrono::seconds(1));cout<<"two"<<endl;int sum=result.get();cout<<"three"<<endl;cout<<sum<<endl;return 0;
}
使用promise和future配合管理异步任务
std::promise提供了⼀种设置值的⽅式,它可以在设置之后通过相关联的std::future对象进⾏读取。换种说法就是之前说过std::future可以读取⼀个异步函数的返回值了, 但是要等待就绪, ⽽std::promise就提供⼀种 ⽅式⼿动让 std::future就绪
我们可以把promise理解为主线程给另一个执行异步任务函数线程放返回值的篮子,但是这个篮子交给另一个线程后无法在给回来,因此主线程需要用promise创建一个future工具从这个篮子中去取返回值
#include<iostream>
#include<thread>
#include<future>
using namespace std;
void Add(int num1,int num2,promise<int> &prom)
{prom.set_value(num1+num2);return ;
}
int main()
{promise<int> prom;future<int> fu=prom.get_future();thread t1(Add,11,22,ref(prom));int res = fu.get();cout<<"sum: "<<res<<endl;t1.join();return 0;
}
使⽤std::packaged_task和std::future配合
std::packaged_task就是将任务和 std::feature 绑定在⼀起的模板,是⼀种对任务的封装。我们可以通过std::packaged_task对象获取任务相关联的std::feature对象,通过调⽤get_future()⽅法获得。std::packaged_task的模板参数是函数签名。
可以把std::future和std::async看成是分开的, ⽽ std::packaged_task则是⼀个整体。
#include<iostream>
#include<thread>
#include<future>
#include<memory>
using namespace std;
//package_task是一个模板类,实例化的对象可以对一个函数进行二次封装
int Add(int num1,int num2)
{return num1+num2;
}
int main()
{auto ptask = make_shared<packaged_task<int(int,int)>>(Add);future<int> fu = ptask->get_future();thread thr([ptask](){(*ptask)(11,22);});int sum = fu.get();cout<<sum<<endl;thr.join();return 0;
}
C++11异步线程池
对于普通的线程池我们只是将任务交给线程执行即可,但是如果我们想要获取任务执行的返回值就要进行类似上面的异步处理;基于线程池执⾏任务的时候,⼊⼝函数内部执⾏逻辑是固定的,因此选择std::packaged_task加上std::future的组合来实现。
线程池工作思想
⽤⼾传⼊要执⾏的函数,以及需要处理的数据(函数的参数),由线程池中的⼯作线程来执⾏函
数完成任务
实现
管理成员
- 任务池:⽤vector维护的⼀个函数任务池⼦
- 互斥锁 & 条件变量: 实现同步互斥
- ⼀定数量的⼯作线程:⽤于不断从任务池取出任务执⾏任务
- 结束运⾏标志:以便于控制线程池的结束
管理的操作
- ⼊队任务:⼊队⼀个函数和参数
- 停⽌运⾏:终⽌线程池
完整代码
class threadpool
{
public:using Functor = std::function<void(void)>;threadpool(int thr_count = 1) : _stop(false){for (int i = 0; i < thr_count; i++){_threads.emplace_back(&threadpool::entry, this);}}~threadpool(){stop();}void stop(){if (_stop == true)return;_stop = true;_cv.notify_all();// 等待所有线程退出for (auto &thread : _threads){thread.join();}}// push传入的首先有一个函数// 不定参数表示要传入函数的参数// push函数内部会将这个传入的函数封装成一个异步任务,抛入任务池中,由工作线程取出执行// 使用lambda表达式生成一个可调用对象,抛入到任务池中,由工作线程取出进行执行// 入队// 函数类型// 参数包template <typename F, typename... Args>auto push(F &&func, Args &&...args) -> std::future<decltype(func(args...))>{// 1.将传入的函数封装一个packaged_task任务using return_type = decltype(func(args...)); // 退出函数返回值对象auto tmp_func = std::bind(std::forward<F>(func), std::forward<Args>(args)...);auto task = std::make_shared<std::packaged_task<return_type()>>(tmp_func);std::future<return_type> fu = task->get_future();// 2。构造一个lambda表达式(捕获任务对象),函数内执行任务对象{std::unique_lock<std::mutex> lock(_mutex);// 3.将构造出来的匿名函数对象,抛入到任务池中_taskpool.push_back([task](){ (*task)(); });_cv.notify_one();}return fu;}private:// 线程入口函数// 不断地从任务池中取任务进行执行void entry(){while (!_stop){std::vector<Functor> tem_taskpool;{// 加锁std::unique_lock<std::mutex> lock(_mutex);// 等待:等待任务池不为空,或者_stop被置位_cv.wait(lock, [this](){ return _stop || !_taskpool.empty(); });// 取出任务执行tem_taskpool.swap(_taskpool);}for (auto &task : tem_taskpool){task();}}}private:std::atomic<bool> _stop;std::vector<Functor> _taskpool; // 任务池std::mutex _mutex;std::condition_variable _cv;std::vector<std::thread> _threads; // 线程池
};
上面异步线程池的完整代码中的语法规则都是C++11的新特性,在核心功能中甚至一行都有好几个的C++11新特性,要想理解上面的代码需要我们非常熟悉新特性;
今天对C++11异步线程池的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!!
相关文章:
【仿RabbitMQ消息队列】基于C++11中packaged_tack异步线程池
目录 什么是同步和异步? future 使用future和async配合管理异步任务 使用promise和future配合管理异步任务 使⽤std::packaged_task和std::future配合 C11异步线程池 什么是同步和异步? 同步(Synchronous) 同步编程是指程…...
免费下载专利
给大家提供一个可以免费下载专利的地方 链接:https://www.drugfuture.com/cnpat/cn_patent.asp...
CentOS7安装流程步骤详细教程
1. 简介 1.1. 概述 CentOS 7是一款基于Red Hat Enterprise Linux(RHEL)的开源Linux发行版,它提供了一个稳定、安全、高效的操作系统,适用于企业级应用、服务器、云计算等领域。CentOS 7以其高度的稳定性和安全性而闻名,它广泛应用于各种行业和领域,包括政府、金融、医疗、…...
【大模型从入门到精通17】openAI API 构建和评估大型语言模型(LLM)应用5
这里写目录标题 理论问题:实践问题:理论实践 理论问题: 1.描述评估LLM应用程序输出的重要性,并提及至少三个维度,这些输出应该在这几个维度上被评估。 2.解释在评估LLM应用程序时开发稳健的性能指标的作用,…...
苹果手机无iCloud备份下“最近删除”照片的恢复策略
iPhone最近删除清空了照片还能恢复吗?大家都知道,照片对于我们来说是承载着美好回忆的一种形式。它记录着我们的平淡生活,也留住了我们的美好瞬间,因此,具有极其重要的纪念价值。但由于我们的失误操作导致照片被删除&a…...
Docker搭建Minio容器
Docker搭建Minio容器 前言 在上一集我们介绍了分布式文件存储行业解决方案以及技术选型。最终我们决定选用Minio作为分布式文件存储。 那么这集我们就在Docker上搭建Minio容器即可。 Docker搭建Minio容器步骤 创建Minio文件目录 我们选择创建/minio/data目录 修改目录权…...
【C++】多源BFS问题和拓扑排序
目录 多源BFS介绍 单源BFS和多源BFS的区别 SO如何解决多源BFS问题 多源之核心 矩阵 算法思路 代码实现 飞地的数量 算法思路 代码实现 地图中的最高点 算法思路 代码实现 地图分析 算法思路 代码实现 拓扑排序介绍 有向无环图 编辑 如何解决这类问题 课…...
CentOS 7 安装详细教程
大家好,我是程序员小羊! 前言: CentOS 7 是一个稳定的企业级 Linux 发行版,广泛用于服务器环境。CentOS 7 是基于 Red Hat Enterprise Linux (RHEL) 构建的企业级 Linux 发行版,提供免费的、开源的操作系统…...
mybatis-plus + springboot 多对多实例
在MyBatis Plus中,自动填充数据是一种非常实用的功能,它可以自动地为一些字段设置默认值,比如创建时间和更新时间。对于多对多关系来说,虽然自动填充主要针对单一实体的字段,但在某些情况下,你可能也需要在…...
SpringBoot日志整合
Spring Boot 整合日志框架的核心是通过 spring-boot-starter-logging 依赖来实现的,它默认整合了 Logback 日志框架。 Spring Boot 对各种日志框架进行了自动配置,使得我们可以很容易地在 Spring Boot 应用中使用日志。 Spring Boot 在类路径下寻找 Log…...
信创教育:培养未来科技创新的生力军
随着全球数字化转型的加速,信息技术应用创新(简称“信创”)产业作为推动国家信息技术自主可控和产业升级的关键领域,正迎来前所未有的发展机遇。信创教育,作为培养未来科技创新生力军的重要阵地,其重要性和…...
slowfast
核心网络网络架构: 1、分别获取高频和低频图像数据 2、分别进行特征提取 3、特征融合 4、预测 网络结构细节:...
怎么调试python脚本
打开pycharm community 2019.1软件,创建一个项目。 创建一个py后缀的文件作为示范,文件名自己定义。 编写代码,然后右键点击进行运行,查看一下是否有问题。 点击右上角的虫子图标,然后下面会有控制面板出来,…...
Flask获取请求信息
示例代码 from flask import Flaskapp = Flask(__name__)if __name__ == "__main__": app.run(debug=True) 1、获取请求头 from flask import request@app.route("/headers", methods=["GET"])def get_headers(): headers = request.heade…...
Overleaf中放置高分辨率图片的方法
如果将ppt中的图片另存为png或jpg等格式,如果图中有密集的编码网格,则生成的pdf会糊掉。如何确保生成的pdf中的图片放大后仍然保持细节?亲测方案: 1、将ppt中的图片尺寸记下来,然后在ppt→设计中将ppt模板的大小设置成…...
【C语言】动态内存管理(malloc,free,calloc,realloc详解 )
🦄个人主页:小米里的大麦-CSDN博客 🎏所属专栏:https://blog.csdn.net/huangcancan666/category_12718530.html 🎁代码托管:C语言: C语言方向(基础知识和应用) (gitee.com) ⚙️操作环境:Visual Studio 2022 目录 一、…...
如何寻找数值仿真参数最优解?CFD参数优化详解3来袭
本期文章将通过2个简单案例演示参数优化的操作步骤,一起来看看吧! 流程自动化 实现 CFD 参数优化,首先要创建流程自动化。用户可采用SimLab的Python宏命令,录制建模流程。或在HyperWorks CFD模块的Template Manager创建Tcl/Tk命令…...
虚拟机macos中构建llvm、clang并配置Xcode
安装虚拟机macos,并安装brew: 安装vmware:https://www.bilibili.com/video/BV1Wo4y1E7fc/安装最新版的macos:极限苹果-Mac论坛-提供Mac软件和macOS苹果系统镜像下载下载并安装brew:版本要低,我装的是4.3.5…...
Java 中的 @SneakyThrows 注解详解:简化异常处理的利与弊
在 Java 开发中,异常处理是一个不可避免的重要部分。我们经常需要处理各种检查型异常(checked exceptions),这有时会导致代码变得冗长且难以维护。为了简化异常处理,Lombok 提供了一个强大的注解——SneakyThrows。本文…...
系统编程 day11 进程(线程)3
fork函数的总结: 总结对进程学习之中的回收函数wait wait函数: 1.获取子进程的退出状态 2.回收资源------会让僵尸态的子进程销毁 注:1.wait函数本身是一个阻塞操作,会使调用者阻塞 2.父进程要获得子进程的退出状态 子进程&…...
AI原生运维体系必须跨越的3道生死线:数据治理、模型可观测性、人机协同SLA(SITS 2026闭门研讨纪要)
更多请点击: https://intelliparadigm.com 第一章:AI原生运维体系构建:SITS 2026智能运维专场精华 AI原生运维(AIOps Native)已从概念验证迈入生产就绪阶段。SITS 2026智能运维专场首次提出“感知-推理-执行-进化”四…...
Error response from daemon: client version 1.52 is too new. Maximum supported API version is 1.43
按照习惯,输入“docker ps”查看一下容器,结果给我来个这个错误:Error response from daemon: client version 1.52 is too new. Maximum supported API version is 1.43查了一下原因:这是因为使用云构建安装的默认 Docker 守护程…...
NPYViewer:5分钟上手的数据可视化神器,告别NumPy数组查看烦恼
NPYViewer:5分钟上手的数据可视化神器,告别NumPy数组查看烦恼 【免费下载链接】NPYViewer Load and view .npy files containing 2D and 1D NumPy arrays. 项目地址: https://gitcode.com/gh_mirrors/np/NPYViewer 还在为NumPy二进制文件头疼吗&a…...
别再只用Matplotlib画图了!用Python这3个库(SciPy, NumPy, Scikit-learn)给你的数据曲线做个‘美容’
Python数据平滑三剑客:用Savitzky-Golay、插值与滑动平均打造专业级图表 当你面对满是噪点的折线图时,是否想过这些锯齿状的波动正在掩盖数据的真实故事?就像摄影师不会直接发布未经修饰的RAW格式照片,数据科学家也需要掌握图表美…...
AI赋能区域创新评估:融合记分板与政策文本分析的协同框架与实践
1. 项目概述与核心价值 最近在梳理区域创新政策与人工智能应用交叉领域的工作时,我深度实践了一个项目,核心是探讨如何将欧盟的“区域创新记分板”这套成熟的评估体系,与新兴的AI政策分析工具进行深度融合与协同应用。这听起来可能有些学术化…...
AI 基本面量化:从理论到可部署 MVP-1.学习目标与工具链
AI 基本面量化实战:从理论到可部署 MVP 的完整学习路径1. 核心目标与 MVP 定义1.1 学习目标定位1.1.1 掌握 AI 技术与基本面分析深度融合的方法论体系AI 基本面量化的本质并非用复杂模型替代经典金融理论,而是以经济学逻辑为锚、以数据驱动为翼ÿ…...
AI工具搭建自动化视频生成输出审核
# AI工具搭建视频生成中的数据脱敏:一个Python开发者的实战笔记 做视频自动生成这件事,碰到的第一个坎往往不是技术选型,而是数据安全。特别是当视频里要展示真实用户数据的时候,总不能把用户的姓名、手机号、住址这些敏感信息直接…...
LinkSwift:九大网盘直链解析工具使用指南
LinkSwift:九大网盘直链解析工具使用指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / 迅雷云…...
ThinkPad风扇控制终极指南:TPFanCtrl2实现128级精准调速与双风扇独立管理
ThinkPad风扇控制终极指南:TPFanCtrl2实现128级精准调速与双风扇独立管理 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 TPFanCtrl2是一款专为ThinkPad笔记…...
TikTok评论采集终极指南:5分钟学会免费批量提取用户评论
TikTok评论采集终极指南:5分钟学会免费批量提取用户评论 【免费下载链接】TikTokCommentScraper 项目地址: https://gitcode.com/gh_mirrors/ti/TikTokCommentScraper 想要快速获取TikTok视频下的所有用户评论进行数据分析?TikTokCommentScraper…...
