C++线程池介绍和C++代码实现
1、介绍
1.1 线程池应用场景
在进行创建线程任务时,如果需要频繁的创建线程、销毁线程,这样会极大地降低效率,因为创建线程也是需要时间的,一个完整的线程处理运行时间包括:线程的创建时间、线程运作时间、线程的销毁时间。
对于频繁创建线程的业务场景,我们可以预先创建多个线程,在创建多线程任务时,我们可以直接将线程函数添加到预先创建的线程中,这样就可以避免多次创建线程的时间,提高代码运行效率。
1.2 线程池设计的思路
设计多线程主要实现的功能有:(1)预设创建线程的数量。(2)存储运行一定数量线程任务容器workerThread变量(可以是vector或其他容器,元素类型是std::thread),该容器一直检测任务队列变量中是否有待执行的任务,有:则取出执行,没有:则等待。(3)用于存储运行任务的变量Task(数据类型是queue,数据类型是std::function<T>),该变量主要用于存储待运行线程函数func。
线程池理论可以参考链接如下:
深入解析C++编程中线程池的使用_c++线程池用法_歌行梅村的博客-CSDN博客
1.3 线程池设计注意事项
所需理论知识
创建具有适配所有线程函数的任务队列Task,创建这样的任务队列需要有一定的C++基础,可能需要如下知识点:
可变参数模板:template <class... Args>_我在这里啊@的博客-CSDN博客
C++多线程之旅-future等待事件_或许 没有的博客-CSDN博客
C++中函数对象模板function<T>、通用函数适配器std::bind和lambda_c++function头文件_夜雨听萧瑟的博客-CSDN博客
C++多线程中共享变量同步问题_夜雨听萧瑟的博客-CSDN博客
1.4 预设的线程数量是多少?
预设的线程数量不是说越多越好,而是创建适当数量的线程数,让CPU的利用率达到最大。如果预设的线程数量过大,PC的核数有限,这样同时只会有一小部分任务在同步运行,这样操作系统就需要不断的切换上下文,频繁的切换上下文也需要时间,这样反而会降低运行效率。
经验值
主要有下面几种:
(1) 设置线程数量的一般经验值为:2N(N是CPU核数)
(2) 2N+1(N是CPU核数)
(3) N+1(N是CPU核数)
具体设置数量可以在设置后,对其不同数量线程数运行效率进行简单的测试。
具体分析
可参考链接:
线程池创建线程数量讨论_夜雨听萧瑟的博客-CSDN博客
2、简单demo
(1)该demo的中心思想是创建10个运行的线程函数的容器workerThread,该线程不断检测任务队列中是否有待处理任务,有待处理任务则取出,执行任务。(2)创建一个管理任务队列数量容器Task,用户可以向其添加任务。
threadpoolm.h文件如下:
#pragma once
#include <mutex>
#include <condition_variable>
#include <thread>
#include <vector>
#include <queue>
#include <functional>class threadPoolM
{public:using funcType = std::function<void()>;threadPoolM();~threadPoolM();void setThreadNum(int num);void AddTask(const funcType& pf);
private:void StartWork();void RunTask();int m_num;std::vector<std::thread>workerThread;std::mutex mut;std::condition_variable cond;std::queue<funcType> Task;
};
threadpoolm.cpp文件如下:
#include "threadpoolm.h"
#include <iostream>
threadPoolM::threadPoolM()
{}threadPoolM::~threadPoolM()
{for(int i = 0; i < workerThread.size(); i++){workerThread.at(i).join();}
}void threadPoolM::setThreadNum(int num)
{m_num = num;StartWork();
}void threadPoolM::AddTask(const threadPoolM::funcType& pf)
{std::unique_lock<std::mutex>lk(mut);cond.wait(lk,[this]{return Task.size() < 10;});Task.push(pf);std::cout <<"id " << std::this_thread::get_id() << ", add a task, size is " << Task.size() << std::endl;cond.notify_one();}void threadPoolM::StartWork()
{for(int i = 0; i < m_num; i++){workerThread.push_back(std::thread(&threadPoolM::RunTask,this));}
}void threadPoolM::RunTask()
{while (true) {std::unique_lock<std::mutex>lk(mut);cond.wait(lk,[this]{return Task.size()>0;});auto Ta = std::move(Task.front());Task.pop();Ta();std::cout <<"id " << std::this_thread::get_id() << ", run a task,size" << Task.size() << std::endl;cond.notify_one();}
}
上面线程池类的使用main.cpp如下:
#include <iostream>
#include "threadpoolm.h"
int cnt = 0;void printId(int id)
{std::cout << "id " << std::this_thread::get_id() << ", id" << id << std::endl;
}
int main()
{std::cout << "Hello World!" << std::endl;threadPoolM pool;pool.setThreadNum(10);while(true){if(cnt++ > 2000){cnt = 0;}std::cout << "cnt " << cnt << std::endl;auto f1 = std::bind(printId,cnt);pool.AddTask(f1); std::this_thread::sleep_for(std::chrono::milliseconds(100));//主线程中的while循环,只是对实际添加任务消息进行模拟,故没有退出while条件。}return 0; //由于线程池中的RunTask函数存在while循环,没有退出条件,所以该行代码不会执行。可以按照实际条件对其while条件修改。
}
运行结果如下:

上面的代码参考于
c++11最简单的线程池实现_c++实现线程池_osDetach的博客-CSDN博客
线程池的实现代码也可参考下面链接:
基于c++11的100行实现简单线程池_c++11 100行实现线程池 csdn_6plus的博客-CSDN博客
附加知识
怎样理解线程的睡眠,挂起,和阻塞? - 知乎 (zhihu.com)
“阻塞(pend)”与“挂起(suspend)”的区别?_pend group run cpu调度_zhch152的博客-CSDN博客
相关文章:
C++线程池介绍和C++代码实现
1、介绍 1.1 线程池应用场景 在进行创建线程任务时,如果需要频繁的创建线程、销毁线程,这样会极大地降低效率,因为创建线程也是需要时间的,一个完整的线程处理运行时间包括:线程的创建时间、线程运作时间、线程的销毁…...
【day 06】vue的组件
组件 组件就是把一个网页分割成独立的小的模块,然后通过把模块进行组合,构建成一个大型的应用 单文件组件 只有一个组件 html css js 都在这个文件内 非单文件组件 可有多个组件 全局注册 !! 得先注册子组件 再生成 vm实例对象 创建子组件 const …...
第3章 Class and Object
构造函数 Guaranteed initialization with the constructor使用构造函数保证初始化 • If a class has a constructor, the compiler automatically calls that constructor at the point an object is created, before client programmers can get their hands on the o…...
卫星定位北斗芯片AT6558一款高性能BDS/GNSS多模卫星导航接收机SOC单芯片
1 芯片简介 AT6558R是一款高性能BDS/GNSS多模卫星导航接收机SOC单芯片,片上集成射频前端, 数字基带处理器,32位的RISCCPU,电源管理功能。 芯片支持多种卫星导航系统,包括中国的北斗卫星导航系统BDS,美国的GPS,俄罗斯 的…...
提升您的 MQTT 云服务:深入探索 BYOC
引言 您是否希望将物联网基础设施提升到更高的水平?为了应对业务的不断扩展,您需要一个强大且安全的消息平台来支持它。 MQTT 协议凭借其轻量级、发布/订阅模型和可靠性,已经成为构建物联网平台的首选方案。但是,随着业务的增长…...
Zookeeper面试题总结
1、说说 Zookeeper 是什么? 有些软件你想做成集群或者分布式,你可以用 ZooKeeper 帮你来辅助实现。特点:ZooKeeper 的特点:维护、协调、管理、监控 最终一致性:客户端看到的数据最终是一致的。可靠性:服务…...
如何使用HTML、CSS和JavaScript来制作这两种类型的时钟
随着计算机技术的不断发展和普及,人们对于时间的精准度要求也越来越高。时钟作为我们日常生活必不可少的工具之一,也得到了越来越多的关注和研究。而在Web开发中,我们同样可以使用HTML、CSS和JavaScript的组合,制作出各式各样的时…...
Java中操作Xml使用备忘
List item 文章目录 Java中操作Xml使用备忘1. Hutool中XmlUtil的使用简介2. Hutool中XmlUtil快速读取Xml字符串某个节点值 [简单取值时,推荐使用]2-1 Hutool工具包Maven依赖和测试Xml字符串如下2-2 读取Xml中的节点<message>的值 3. Hutool中XmlUtil详细操作示…...
【Java|基础篇】内部类
文章目录 1.什么是内部类?2.实例内部类3.静态内部类4.局部内部类5.匿名内部类6.结语 1.什么是内部类? 内部类就是在一个类中再定义一个类,内部类也是封装的体现.它可以被声明为 public、protected、private 或默认访问控制符。内部类可以访问外部类的所有成员变量和方法&…...
七牛云图床设置
文章目录 七牛云图床设置下面是用picgo配置图床SSL证书申请https网站显示http图片解决方案 原文链接图床设置,免费SSL证书申请,https网站显示http链接的图片 七牛云图床设置 登录七牛云官网并进行个人注册,然后找到对象存储 点击空间管理&a…...
Android 12.0下拉状态栏录屏去掉弹窗直接录屏
1.概述 在12.0的系统rom开发中,在systemui的下拉状态栏中有个录屏的快捷按钮,可以通过点击录屏实现录屏功能,但是在录屏的时候发现需要先弹出 dialog,然后点击开始实现录屏,这有的麻烦,所以需要去掉弹窗直接开始录屏,就需要弹窗的相关代码来实现功能 2.下拉状态栏录屏…...
MySql基础学习(1)
MySql基础学习 一、数据库1.1 什么是数据库1.2 MySql的启动与停止1.3 MySql数据模型 二、SQL2.1 SQL通用语法2.2 SQL分类2.2.1 数据类型2.2.2 DDL使用方法2.2.3 、表操作-修改&删除DDL总结 2.3 DML2.3.1 DML添加数据2.3.2 DML---修改数据2.3.3 DML---删除数据DML总结 2.4 D…...
18- 弹幕系统设计
1、弹幕系统设计 场景分析:客户端针对某一视频创建了弹幕,发送后端进行处理,后端需要对所有正在观看该视频的用户推送该弹幕。 1.1、实现方式 使用短连接进行通信或使用长连接进行通信。 1.1.1、短连接实现方案 所有观看视频的客户端不断…...
字节软测划水四年,内容过于真实......
先简单交代一下吧,潇潇是某不知名211的本硕,18年毕业加入一个小厂,之后跳槽到了字节跳动,一直从事测试开发相关的工作。之前没有实习经历,算是四年半的工作经验吧。 这四年半之间他完成了一次晋升,换了一家…...
Mybatis介绍
1. Mybatis中#和$的区别? #相当于对数据 加上 双引号,$相当于直接显示数据 1. #将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为orde…...
Docker理论基础
初识Docker 1.什么是Docker 微服务虽然具备各种各样的优势,但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中,依赖的组件非常多,不同组件之间部署时往往会产生一些冲突。 在数百上千台服务中重复部署,环境不一定一致&…...
MySQL数据库之存储引擎
一、存储引擎的概念 1.1 什么是存储引擎 MySQL中的数据用各种不下同的技术存储在文件中,每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力,这些不同的技术以及配套的功能在MySQL中称为存储引擎。存储引擎是MySQL将数据存…...
中介效应分析全流程汇总
一、中介效应说明 中介效应主要研究自变量对因变量影响的过程中,自变量是否通过中介变量再对因变量产生影响,那什么情况表明中介效应存在呢?如果自变量对因变量影响过程中,中介变量在模型中有着桥梁般的作用,那说明中…...
论文阅读:Multimodal Graph Transformer for Multimodal Question Answering
文章目录 论文链接摘要1 contribution3 Multimodal Graph Transformer3.1 Background on Transformers3.2 Framework overview 框架概述3.3 Multimodal graph construction多模态图的构建Text graphSemantic graphDense region graph Graph-involved quasi-attention 总结 论文…...
关于compile() 函数简单实用示例
compile() 函数是什么 compile() 函数将一个字符串编译为字节代码。 compile将代码编译为代码对象,应用在代码中可以提高效率。 语法 compile(source, filename, mode, flags0, dont_inheritFalse, optimize-1) 参数 source:表示要编译的源代码字符串、…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...
LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
