C++(27): 线程池
目录
1. 概述
2. 例程
(1)ThreadPool.h
(2)ThreadPool.cpp
(3)Start.cpp
(4)编译
1. 概述
线程池技术绝不是C++独有的,Java和Python都有比较晚完善的线程池构造接口。
通俗的讲,线程池只是一种管理线程的方式。很多时候,我们为了充分利用CPU和Memory资源,会创建一些独立的线程,执行同步或异步的任务。但有一个不得不考虑的问题是,现成的创建和销毁本身也是消耗系统资源的,尤其是一些需要频繁创建和销毁线程的应用场景下。当然有时候有一些连续的任务也不需要通过线程池技术来完成。
如上所述,为了避免频繁创建和销毁线程带来的系统资源的消耗,我们可以提前创建一定数量的线程,用来等待和处理队列中的事务,无需反复地创建和销毁线程。
2. 例程
(1)ThreadPool.h
#ifndef __THREADPOOL_H__#define __THREADPOOL_H__#include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <future>#include <functional>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <stdint.h>class ThreadPool{public: ThreadPool(size_t threads);template<class F, class... Args> auto enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type>{using return_type = typename std::result_of<F(Args...)>::type; auto task = std::make_shared<std::packaged_task<return_type()>>( std::bind(std::forward<F>(f), std::forward<Args>(args)...) ); std::future<return_type> res = task->get_future(); { std::unique_lock<std::mutex> lock(queueMutex); if (stop) { throw std::runtime_error("enqueue on stopped ThreadPool"); } tasks.emplace([task]() { (*task)(); }); } condition.notify_one(); return res; }~ThreadPool();private: std::vector<std::thread> workers; std::queue<std::function<void()>> tasks; std::mutex queueMutex; std::condition_variable condition; bool stop; };#endif ///< __THREADPOOL_H__
(2)ThreadPool.cpp
#include "ThreadPool.h"ThreadPool::ThreadPool(size_t threads) : stop(false){for (size_t i = 0; i < threads; ++i) { workers.emplace_back([this] { while (true) { std::function<void()> task; { std::unique_lock<std::mutex> lock(this->queueMutex); this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); }); if (this->stop && this->tasks.empty()) { return; } task = std::move(this->tasks.front()); this->tasks.pop(); } task(); } }); } }ThreadPool::~ThreadPool(){ { std::unique_lock<std::mutex> lock(queueMutex); stop = true; } condition.notify_all(); for (std::thread &worker : workers) { worker.join(); } }
(3)Start.cpp
#include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <future>#include <functional>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <stdint.h>#include "ThreadPool.h"/** sudo g++ -std=c++17 -o ./Start.bin ./*.cpp -lpthread */#define EXTERNAL_FUNC 0 ///< 0: 类内部成员///< 1: 类外部成员#if EXTERNAL_FUNC == 1// 定义一个返回整数的函数 int intFunction(int x){return x * x;} // 定义一个返回字符串的函数 std::string stringFunction(std::string s){return s + " world";}int main(int argc, char* argv[]){ThreadPool pool(4); // 使用enqueue来执行intFunction,传入参数4 auto result1 = pool.enqueue(intFunction, 4); // 使用enqueue来执行stringFunction,传入参数"hello" auto result2 = pool.enqueue(stringFunction, "hello"); // 获取并打印结果 std::cout << "result1: " << result1.get() << std::endl; // 应该打印出16 std::cout << "result2: " << result2.get() << std::endl; // 应该打印出"hello world" return 0; }#else ///< 作为类成员class DemoClass{public: DemoClass(int num_threads = 1){if(num_threads <= 0 ){num_threads = 1;}pool = new ThreadPool(num_threads);}~DemoClass(){delete pool;pool = nullptr;}void printTask(int n){ std::cout << "Processing " << n << std::endl;} void startProcessing(){for (int i = 1; i <= 50; ++i){pool->enqueue(&DemoClass::printTask, this, i);usleep(1); ///< 短暂的等待是有必要的.} }private:ThreadPool* pool = nullptr;}; int main(int argc, char* argv[]){DemoClass myClass(10); myClass.startProcessing(); return 0; }#endif
(4)编译
sudo g++ -std=c++17 -o ./Start.bin ./*.cpp -lpthread
相关文章:
C++(27): 线程池
目录 1. 概述 2. 例程 (1)ThreadPool.h (2)ThreadPool.cpp (3)Start.cpp (4)编译 1. 概述 线程池技术绝不是C独有的,Java和Python都有比较晚完善的线程池构造接口…...

每日一题-贪心算法
122. 买卖股票的最佳时机 II - 力扣(LeetCode) 55. 跳跃游戏 - 力扣(LeetCode) 这个题目一开始肯定是会懵,就比如说一开始先跳几步,之后再怎么跳,其实我们就可以用最大范围来算就行了࿰…...
PSO 算法实例(手动推导过程)
PSO 算法实例 引言正文PSO 算法步骤PSO 实例步骤1 定义目标函数步骤2 初始化每个粒子的位置和速度步骤3 使用目标函数进行评估步骤4 更新单个粒子的最佳位置(局部最优值)步骤5 更新全局最佳位置(全局最优值)步骤6 更新每个粒子的位置和速度步骤7 使用目标函数评估新的位置步…...
解决antd TreeSelect 返回值不包含父节点问题 -自定义组件(react)
在写一个表单时使用了antd的 TreeSelect,在对TreeSelect的值提交时发现,父节点的值在半选状态时未提交,在选中状态时(子节点全选),子节点不提交,只提交父节点,这与后端需求不符&…...

花四小时,写了个在线实时绘制等值面图小软件,明晚上线,喜欢的小伙伴关注哦
科研党的福音,绘图再也不需要安装一堆软件了,可以在线绘图了; 只需要传入绘制的区间、色值、以及所需要绘制的数据就可以直接出图了,可绘制各种等值面图,比如降水分布,高温分布,人口分布&#x…...
c++的vector用法
文章目录 1. 创建和初始化 std::vector2. 添加和删除元素3. 访问和遍历元素4. std::vector 的其他常用操作 std::vector 是 C 标准库中的一个动态数组容器,提供了灵活的存储和访问功能。 1. 创建和初始化 std::vector #include <iostream> #include <vect…...

【Linux网络】Linux网络初探:开启网络世界的大门
W...Y的主页 😊 代码仓库分享💕 前言:我们已经系统的学习了Linux的基本操作、进程、线程、文件、通信等待,但是在如今社会没有网络通信方式是万万不行的,今天我们就走进网络中,系统的学习一下有关Linux网…...

目录、用户与组、出错相关函数、时间函数
一、目录相关函数及属性 1、 opendir()函数 opendir 用于打开一个目录,并返回一个目录流指针。name:要打开的目录的路径。 返回值:成功时返回指向目录流的指针,失败时返回 NULL。 #include <dirent.h> DIR *opendir(con…...

<keep-alive> 一分钟了解
<keep-alive> 一分钟了解 <keep-alive> 是 Vue.js 提供的一个抽象组件,它的主要用途是在页面或组件切换时保留其状态,避免重复执行昂贵的渲染操作,从而提升应用性能。 文章目录 <keep-alive> 一分钟了解 一、 <keep-ali…...
Android 启动动画太生硬
跟 android:launchMode"singleTask"属性无关系 请禁用路由 ARouter.getInstance() .build(Routes.Main.MAIN) .withTransition(R.anim.activity_anim_in, R.anim.activity_anim_out).navigation() 正确做法是 val intent Intent(thisSplashActivity,MainActivit…...
深度学习中常用概念总结
最近在做深度学习,里面涉及到很多概念,有的名称都差不多容易记混。所以写这篇文章总结一下。眼过千遍不如手过一遍。 1. 轮数(Epochs): 一轮(Epoch)指的是整个训练数据集在训练过程中被完整使用一次。…...

进 程
1.进程:进行中的程序。 微观串行,宏观并行。 程序的一次执行过程 进程是程序的一个实例 一个程序可以对应一个或多个进程。 2.为什么需要进程? 3.进程的组成部分: 进程 pcb 块 栈|堆|bss|data|text 其中: 家族…...

Taro-UI
一、安装Taro UI 进入项目文件,执行项目 //使用yarn安装taro-ui yarn add taro-ui//使用npm安装taro-ui npm install taro-ui//注:因为要支持自定义主题功能,需要将样式从组件中抽离出来,在微信小程序中依赖 globalClass 功能&a…...

TypeScript 之 JavaScript文件类型检查
启用对 JavaScript 文件的类型检查 在 TypeScript 编译选项 compilerOptions 全部配置项 中,可以通过以下2个属性配置 JavaScript Support: allowJs 是否允许编译 JavaScript 文件。默认值是 false。在默认情况下,TypeScript 编译器只处理 .…...

基本数据类型变量间的自动提升与强制转换以及进制的转换
基本数据类型变量间的自动提升与强制转换 测试基本数据类型的运算规则 这里基本类型不包括布尔 运算规则 自动类型提升 当容量小的变量与容量大的变量做运算时,结果自动转换容量大的数据类型 说明:此时容量大小,指的是数据范围大小&…...
SparseConv 的学习笔记
安装 环境设置在74.183 sdfstudio 里面,SparseNeus 推荐的版本是是 torchsparse 2.0.0版本 命令行如下: 需要 C 的 sudo 权限指定安装: ## 安装依赖项 conda install -c conda-forge sparsehash sudo apt-get install libsparsehash-dev 进入官网下…...

vscode 快速生成vue 格式
1.用快捷Ctrl Shift P唤出控制台 输入“Snippets”并选择 Snippets: Configure User Snippets 2.输入vue,选中vue.json vs code自动生成vue.json文件 3.在 vue.json 中添加模板 {"Print to console": {"prefix": "vue2","b…...

react笔记:redux
redux状态管理 安装redux:num i redux 新建redux文件夹: store.jscount_reducer.js count_action.js constant.js (常量) 1. store.js文件: // 该文件专门用于暴露一个store对象,整个应用只有一个store对…...

数据结构与算法--图的应用
文章目录 回顾提要连通图生成树最小生成树构造最小生成树的算法普里姆(Prim)算法克鲁斯卡尔(Kruskal)算法 最短路径狄杰斯特拉 (Dijkstra) 算法当前最短路径的更新拓扑排序拓扑排序方法拓扑排序示例总结 回顾 图的遍历方法: 深度优先遍历 (DFS):从任意…...

【leetcode图文详解】特殊数组II : 空间换时间的“记忆化”,越多越好吗?
题目详解 需求:判断给定区间内的元素是否满足“特殊数组”要求 尝试: 暴力求解? 如果试着直接对每个queries中的区间进行检测而不做其他处理,那么最后不出意外地超时了。。 细想优化策略,不难察觉到其中可能存在大量的重复运算 那还等什…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...