C++:实现线程池
线程池(Thread Pool)是一种多线程处理方式,用于管理和复用多个线程,以提高程序的并发性能并避免频繁创建和销毁线程所带来的开销。
基本概念:
线程池维护着若干个已创建好的线程,当有任务需要执行时,就从线程池中取出空闲线程来执行任务,任务执行完成后线程并不被销毁,而是返回线程池中继续等待执行下一个任务。
主要优点:
- 减少资源消耗:重复利用已创建的线程,避免频繁创建和销毁线程的开销。
- 提高响应速度:任务到达时可以立即执行(如果有空闲线程),而不必等待创建新线程。
- 提高线程可管理性:线程池可以设置线程的最大并发数,防止系统因为创建过多线程而耗尽资源。
- 任务排队机制:可以统一调度和管理任务,比如按顺序执行、设置优先级、延迟执行等。
使用场景:
- Web 服务器:处理高并发的客户端请求,复用线程,提升效率。
- 数据库连接池:减少数据库连接的创建和销毁,提高性能。
- 任务并行处理:同时处理多个独立任务,减少总执行时间。
- 后台定时任务:定时执行任务或后台处理,避免阻塞主线程。
- IO密集型任务:提高系统资源利用率,如网络请求或磁盘读写。
实现
class ThreadPool {
public:// 默认构造函数ThreadPool() = default;// 移动构造函数ThreadPool(ThreadPool&&) = default;// 带线程数参数的构造函数,默认启动 8 个线程explicit ThreadPool(size_t thread_count = 8) : pool_(std::make_shared<Pool>()) {// 启动 thread_count 个线程for (size_t i = 0; i < thread_count; ++i) {std::thread([this]() {// 每个线程执行的任务std::unique_lock<std::mutex> locker(pool_->mtx_);while (true) {// 如果任务队列不为空,则取任务并执行if (!pool_->tasks_.empty()) {// 从任务队列中取出任务并执行auto task = std::move(pool_->tasks_.front());pool_->tasks_.pop();locker.unlock(); // 执行任务时不需要保持锁task(); // 执行任务locker.lock(); // 执行完任务后重新加锁} // 如果任务队列为空且线程池未关闭,则等待新任务else if (!pool_->stop_) {pool_->cond_.wait(locker); // 等待任务或关闭信号} // 如果线程池已关闭,退出线程else {break;}}}).detach(); // 分离线程,确保线程池的生命周期独立于调用者}}// 析构函数,关闭线程池,确保所有线程停止~ThreadPool() {if (pool_) {// 设置停止标志,通知所有线程退出std::lock_guard<std::mutex> locker(pool_->mtx_);pool_->stop_ = true;}// 唤醒所有等待中的线程,让它们退出pool_->cond_.notify_all();}// 添加任务到任务队列template<class T>void addTask(T&& task) {std::lock_guard<std::mutex> locker(pool_->mtx_); // 加锁确保线程安全pool_->tasks_.push(std::forward<T>(task)); // 将任务添加到队列pool_->cond_.notify_one(); // 通知一个线程执行任务}private:// 用于管理线程池的内部结构struct Pool {bool stop_; // 标志线程池是否关闭std::mutex mtx_; // 保护任务队列的互斥锁std::condition_variable cond_; // 条件变量,用于等待任务std::queue<std::function<void()>> tasks_; // 存储任务的队列};// 线程池的共享资源std::shared_ptr<Pool> pool_;
};
更高级的实现,A simple C++11 Thread Pool implementation
class ThreadPool {
public:// 构造函数,传入线程数量ThreadPool(size_t);// 添加任务到线程池,返回一个 future 对象,用于获取异步任务结果template<class F, class... Args>auto enqueue(F&& f, Args&&... args)-> std::future<typename std::result_of<F(Args...)>::type>;// 析构函数,回收线程~ThreadPool();private:// 工作线程集合,用于管理线程对象std::vector<std::thread> workers;// 任务队列,存放待执行的任务(函数对象)std::queue<std::function<void()>> tasks;// 互斥锁,保证任务队列线程安全std::mutex queue_mutex;// 条件变量,用于线程之间通信,通知有新任务或者停止std::condition_variable condition;// 停止标志,标识线程池是否停止接收新任务bool stop;
};// 构造函数:初始化线程池,创建 threads 个线程
inline ThreadPool::ThreadPool(size_t threads): stop(false) // 初始时线程池不停止
{for (size_t i = 0; i < threads; ++i)// 创建线程并加入 workers 容器workers.emplace_back([this] {for (;;) { // 每个线程不断循环取任务执行std::function<void()> task;{// 加锁,保证线程安全访问任务队列std::unique_lock<std::mutex> lock(this->queue_mutex);// 如果任务队列为空且线程池未关闭,则阻塞等待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();}});
}// 添加任务到线程池,并返回 future 获取结果
template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args)-> std::future<typename std::result_of<F(Args...)>::type>
{// 定义任务返回值类型using return_type = typename std::result_of<F(Args...)>::type;// 将传入的函数和参数绑定,生成 packaged_task(带返回值的可调用对象)auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));// 获取该任务对应的 future,用于异步获取结果std::future<return_type> res = task->get_future();{// 加锁保护任务队列std::unique_lock<std::mutex> lock(queue_mutex);// 如果线程池已经停止,抛异常if (stop)throw std::runtime_error("enqueue on stopped ThreadPool");// 将任务加入任务队列,任务是一个无参 void() 函数对象tasks.emplace([task]() { (*task)(); });}// 通知一个线程有新任务了condition.notify_one();// 返回 futurereturn res;
}// 析构函数,停止线程池,回收所有线程
inline ThreadPool::~ThreadPool()
{{// 加锁修改停止标志std::unique_lock<std::mutex> lock(queue_mutex);stop = true;}// 唤醒所有阻塞中的线程,让它们检查 stop 状态并退出condition.notify_all();// 等待所有线程结束for (std::thread &worker : workers)worker.join();
}
测试
#include <iostream>
#include "threadpool.h"int main() {ThreadPool pool(4);for (int i = 0; i < 10; ++i) {pool.addTask([i] {std::cout << "Task " << i << " running in thread " << std::this_thread::get_id() << std::endl;});}std::this_thread::sleep_for(std::chrono::seconds(1)); // 简单等一下
}
相关文章:
C++:实现线程池
线程池(Thread Pool)是一种多线程处理方式,用于管理和复用多个线程,以提高程序的并发性能并避免频繁创建和销毁线程所带来的开销。 基本概念: 线程池维护着若干个已创建好的线程,当有任务需要执行时&…...
本地运行qwen3:30b-a3b速度测试
仍然使用的是ollama,运行的Q4_K_M量化版。 这个模型在相同硬件环境下对比我电脑上其他32b的模型速度(小于3 tokens/s)提升非常明显,并且可以设置是否打开思考模式。 注意: /no_think前有个空格 非思考模式࿱…...
keil+vscode+腾讯ai助手
嵌入式软件开发 这个是之前一直想写的开发方式,不过上份工作一直在忙,没有抽出时间花在上面,现在空下来好好写一写吧!标题软件安装 关于VSCode以及Keil的安装可以在以下链接中点击浏览 VSCode安装 Keil5安装 CubeMx安装 插件下…...
通过TinyML为语音助手赋能,推动以用户为中心的创新和现实世界应用
英文标题:Empowering voice assistants with TinyML for user-centric innovations and real-world applications 中文标题:通过TinyML为语音助手赋能,推动以用户为中心的创新和现实世界应用 作者信息 Sireesha Chittepu1, Sheshikala Mart…...
学习Python网络爬虫的实例
30岁程序员学习Python的第二天之网络爬虫的练习实例 爬取软科2025年中国大学排名 思路: 1、百度查到到网页地址:https://www.shanghairanking.cn/rankings/bcur/2025 2、编写爬取代码,具体步骤分3步,第一步通过requests库爬取网…...
雨云游戏云MCSM面板服使用教程我的世界Forge服务端开服教程
雨云 - 新一代云服务提供商 雨云面板服目前支持一键开服的游戏有:Minecraft Java版、Minecraft 基岩版、泰拉瑞亚、饥荒,还提供纯Java/Linux环境(Docker),方便开自己开其他游戏服。 其中Minecraft Java版支持一键开…...
关于loadstartcode使用
loadstartcode 命令用于从 TFTP 服务器下载一个名为 startcode 的文件。这个命令通常用于将启动代码(如引导加载程序或内核启动映像)从 TFTP 服务器加载到设备内存中。它是嵌入式设备和网络设备(如路由器)常见的命令,通…...
Linux死锁实验分析与总结
三、实验结果截图及分析 1. 实验代码 #include <pthread.h> #include <stdio.h> #include <unistd.h>pthread_mutex_t mutex1 PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex2 PTHREAD_MUTEX_INITIALIZER;void* producer(void* arg) {while (1) {pth…...
【计网】ipconfig、ping、arp、tracert
目录 ipconfig ping arp tracert cmd ipconfig ipcofig -all IPv4 物理地址 ping 检测网络连通情况,分析网络速度 根据域名得到服务器IP 根据TTL判断对方所使用的操作系统以及数据包经过路由器数量 byte数据包大小 time响应时间 TTLDNS记录在DNS服务器上存在…...
当手机开始预判你的下一步:一场正在颠覆生活的AI静默革命
当手机开始预判你的下一步:一场正在颠覆生活的AI静默革命 深夜加班时,手机自动调暗屏幕亮度;出差途中,智能音箱提前预定好常去的酒店;打开购物APP,推荐清单里躺着昨天刚在聊天中提到的商品——这些场景背后…...
【SDRS】面向多模态情感分析的情感感知解纠缠表征转移
abstract 多模态情感分析(MSA)旨在利用多模态的互补信息对用户生成的视频进行情感理解。现有的方法主要集中在设计复杂的特征融合策略来整合单独提取的多模态表示,忽略了与情感无关的信息的干扰。在本文中,我们提出将单模表征分解为情感特定特征和情感独立特征,并将前者融…...
C++ 中的静态链接和动态链接详解
目录 一、什么是链接? 链接分为两类: 二、静态链接(Static Linking) 特点: 优点: 缺点: 使用方式: 三、动态链接(Dynamic Linking) 特点: 优…...
426、N叉树的层序遍历
输入检查: if not root:return [] 如果根节点为空,直接返回空列表 初始化: result [] queue collections.deque([root]) result用于存储最终结果queue初始化包含根节点,使用双端队列实现 主循环: while queue:leve…...
雅思阅读--重点短语/句式39个
文章目录 1. according to2. regardless of3. make/keep/leave + n. + adj.leave us stronger1. according to “according to(根据)”。 德国著名数学家 David Hilbert(大卫希尔伯特)说过: Mathematics is a game played according to certain simple rules with meanin…...
探索开源大模型体系:当今AI的引领者
目录 1. Hugging Face Transformers 2. OpenAI GPT 3. DeepSpeed 4. Megatron-LM 5. AllenNLP 总结 在当今人工智能的迅猛发展中,大模型(Large Model)已经成为了AI领域的核心。与传统的机器学习模型相比,大模型在自然语言处…...
n8n系列(1)初识n8n:工作流自动化平台概述
1. 引言 随着各类自动化工具的涌现,n8n作为一款开源的工作流自动化平台,凭借其灵活性、可扩展性和强大的集成能力,正在获得越来越多技术团队的青睐。 本文作为n8n系列的开篇,将带您全面了解这个强大的自动化平台,探索其起源、特性以及与其他工具的差异,帮助您判断n8n是否…...
n8n 与智能体构建:开发自动化 AI 作业的基础平台
n8n 是一款开源的自动化流程构建平台,通过其模块化节点系统,开发者可以快速实现跨平台的任务编排、数据集成与智能交互。当 n8n 与大型语言模型(LLM)结合时,就能构建出具备感知、推理、执行能力的 AI 智能体࿰…...
大模型主干
1.什么是语言模型骨架LLM-Backbone,在多模态模型中的作用? 语言模型骨架(LLM Backbone)是多模态模型中的核心组件之一。它利用预训练的语言模型(如Flan-T5、ChatGLM、UL2等)来处理各种模态的特征,进行语义…...
大模型在宫颈癌诊疗全流程预测与应用研究报告
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、大模型预测宫颈癌术前风险 2.1 术前数据收集与预处理 2.2 预测模型构建与算法选择 2.3 术前风险预测指标与案例分析 三、大模型辅助制定术中方案 3.1 术中风险动态监测与预测 3.2 基于预测的手术方案优化…...
Diffusion Transformer(DiT)
扩散模型的核心思想:Diffusion Models是一种受到非平衡热力学启发的生成模型,其核心思想是通过模拟扩散过程来逐步添加噪声到数据中,并随后学习反转这个过程以从噪声中构建出所需的数据样本。 DiT的架构:DiT架构基于Latent Diffu…...
多模态理论知识
说一下多模态的定义? 多模态是指使用多种不同类型的媒体和数据输入,例如文本、图像、音频、视频等,它们之间存在关联或者对应关系。 这些不同类型的媒体和数据输入可以在不同的层面上传达信息并表达意义。多模态数据的处理需要融合不同类型的信息&…...
Nginx 安全防护与HTTPS部署
目录 一、核心安全配置 1、隐藏版本号 2、限制危险请求方法 3、请求限制(CC攻击防御) (1)使用Nginx的limit_req模块限制请求速率 (2)压力测试验证 4、防盗链 (1)修改 Window…...
Python爬虫+代理IP+Header伪装:高效采集亚马逊数据
1. 引言 在当今大数据时代,电商平台(如亚马逊)的数据采集对于市场分析、竞品监控和价格追踪至关重要。然而,亚马逊具有严格的反爬虫机制,包括IP封禁、Header检测、验证码挑战等。 为了高效且稳定地采集亚马逊数据&am…...
效率提升利器:解锁图片处理新姿势
今天我给大家分享一款超实用的图片压缩软件,好用程度超出想象!该软件身形 “轻盈”,仅 648KB,启动后能迅速上手。 01 软件介绍 这款软件就是PicSizer,具有以下特点: 支持windows系统 体积小,绿…...
【强化学习】什么是强化学习?2025
1. 强化学习简介 一句话总结:强化学习(Reinforcement Learning, RL)是一种机器学习范式,强调智能体(agent)通过与环境(environment)的交互,以试错(trial‑an…...
富文本编辑器的第三方库ProseMirror
如果0-1的开发一个富文本编辑器,成本还是非常高的,里面很多坑要踩,市面上很多库可以帮助我们搭建一个富文本编辑器,ProseMirror就是其中最流行的库之一。 认识ProseMirror ProseMirror 提供了一套工具和概念,用于构建…...
理解IP四元组与网络五元组:网络流量的“身份证”
理解IP四元组与网络五元组:网络流量的“身份证” 在现代网络通信中,IP四元组和网络五元组是流量识别、连接追踪、安全策略等核心的基础概念。理解这些“元组”不仅能够帮助我们更好地设计网络架构、排查故障,还能为安全与运维策略的落地提供…...
ROS2:话题通信CPP语法速记
目录 发布方实现流程重点代码 订阅方实现流程重点代码 参考代码示例发布方代码订阅方代码 发布方实现流程 包含头文件(rclcpp.hpp与[interfaces_pkg].hpp)初始化ROS2客户端(rclcpp::init)自定义节点类(创建发布实例,伺…...
码蹄集——直线切平面、圆切平面
MT1068 直线切平面 思路: 则 #include<bits/stdc.h> using namespace std;int main( ) {int n;cin>>n;cout<<n*(n1)/21;return 0; } MT1069圆切平面 n个圆最多把平面分成几部分?输入圆的数量N,问最多把平面分成几块。比如…...
2025年游戏行业DDoS攻防指南:智能防御体系构建与实战策略
2025年,游戏行业在全球化扩张与技术创新浪潮中,正面临前所未有的DDoS攻击威胁。攻击规模从T级流量到AI驱动的精准渗透,攻击手段从传统网络层洪水到混合型应用层打击,防御体系已从“被动应对”转向“智能博弈”。本文将结合最新攻击…...
LightGBM算法原理及Python实现
一、概述 LightGBM 由微软公司开发,是基于梯度提升框架的高效机器学习算法,属于集成学习中提升树家族的一员。它以决策树为基学习器,通过迭代地训练一系列决策树,不断纠正前一棵树的预测误差,逐步提升模型的预测精度&a…...
Nvidia发布Parakeet V2,一款新的开源自动语音识别模型
Nvidia 发布 Parakeet V2,一款新的开源自动语音识别 AI,核心亮点:一秒钟转录一小时的音频;Open ASR 上的顶级模型,击败了 ElevenLabs 的 Scribe 和 OpenAI 的 Whisper;6.05% 的单词错误率;CC-BY…...
浅析MySQL 的 **触发器(Trigger)** 和 **存储过程(Stored Procedure)原理及优化建议
MySQL 的 触发器(Trigger) 和 存储过程(Stored Procedure) 是数据库中用于实现业务逻辑的重要机制,它们的原理和使用方式不同,适用于不同的场景。 一、基本概念与原理 特性触发器(Trigger)存储过程(Stored Procedure)定义在表上定义,当特定事件(INSERT/UPDATE/DELE…...
网页版部署MySQL + Qwen3-0.5B + Flask + Dify 工作流部署指南
1. 安装MySQL和PyMySQL 安装MySQL # 在Ubuntu/Debian上安装 sudo apt update sudo apt install mysql-server sudo mysql_secure_installation# 启动MySQL服务 sudo systemctl start mysql sudo systemctl enable mysql 安装PyMySQL pip install pymysql 使用 apt 安装 My…...
人工智能与智能合约:如何用AI优化区块链技术中的合约执行?
引言:科技融合的新风口 区块链和人工智能,是当前最受瞩目的两大前沿技术。一个以去中心化、可溯源的机制重构信任体系,另一个以智能学习与决策能力重塑数据的价值。当这两项技术相遇,会碰撞出什么样的火花? 智能合约作…...
如何提升丢包网络环境下的传输性能:从 TCP 到 QUIC,再到 wovenet 的实践
在现代互联网环境中,稳定、可靠的网络连接对各种在线应用至关重要。然而,理想情况往往难以实现,特别是在以下一些典型场景中,网络丢包(packet loss) 常常发生: 一、常见的网络丢包场景 跨境通…...
Python 中的数据结构介绍
Python 是一种功能强大的编程语言,它内置了多种数据结构,以便用户能够方便、高效地存储、处理和访问数据。数据结构是组织和存储数据的方式,不同的数据结构适用于不同的应用场景。掌握 Python 中的基本数据结构,可以使代码更加简洁…...
数据中台架构设计
数据中台分层架构 数据采集层 数据源类型:业务系统(ERP、CRM)、日志、IoT 设备、第三方 API 等。采集方式: 实时采集:Kafka、Flink CDC(变更数据捕获)。离线采集:Sqoop、DataX&…...
基于SpringBoot网上书店的设计与实现
pom.xml配置文件 1. 项目基本信息(没什么作用) <groupId>com.spring</groupId> <!--项目组织标识,通常对应包结构--> <artifactId>boot</artifactId> <!--项目唯一标识--> <version>0.0.1-SNAPSHOT</ve…...
Vue3路由模式为history,使用nginx部署上线后刷新404的问题
一、问题 在使用nginx部署vue3的项目后,发现正常时可以访问的,但是一旦刷新,就是出现404的情况 二、解决方法 1.vite.config.js配置 在vite.config.js中加入以下配置 export default defineConfig(({ mode }) > {const isProduction …...
从单机到生产:Kubernetes 部署方案全解析
🚀 从单机到生产:Kubernetes 部署方案全解析 🌐 Kubernetes(k8s)是当今最流行的容器编排系统,广泛应用于开发、测试和生产环境。但不同的使用场景对集群规模、高可用性和资源需求有不同的要求。本文将带你…...
redis大全
1 redis安装和简介 基于ubuntu系统的安装 sudo apt update sudo apt install redis##包安装的redis 没有默认配置文件 启动 redis-server /path/to/your/redis.confredis-cliRedis 默认是没有设置用户和密码的,即可以无密码访问 设置密码的方法:可以通…...
C#经典算法面试题
C#经典算法面试题 递归算法 C#递归算法计算阶乘的方法 一个正整数的阶乘(factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。自然数n的阶乘写作n!。1808年,基斯顿卡曼引进这个表示法。 原理:亦即n!=123…(n-1)n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!n。…...
cephadm部署ceph集群
一、什么是Ceph? ceph是一个统一的、分布式的存储系统,设计初衷式提供较好的性能(io)、可靠性(没有单点故障)和可扩展性(未来可以理论上无限扩展集群规模),这三点也是集群架构所追求的。 “统一的”:意味着Ceph可以一套存储系统同时提供对象存储、块存…...
c#OdbcDataReader的数据读取
先有如下c#示例代码: string strconnect "DSNcustom;UIDsa;PWD123456;" OdbcConnection odbc new OdbcConnection(strconnect); odbc.Open(); if (odbc.State ! System.Data.ConnectionState.Open) { return; } string strSql "select ID from my…...
代码随想录训练营第十八天| 150.逆波兰表达式求值 239.滑动窗口最大值 347.前k个高频元素
150.逆波兰表达式求值: 文档讲解:代码随想录|150.逆波兰表达式求值 视频讲解:栈的最后表演! | LeetCode:150. 逆波兰表达式求值_哔哩哔哩_bilibili 状态:已做出 思路: 这道题目是让我们按照逆波…...
数据中台产品功能介绍
在数字化转型浪潮中,数据中台作为企业数据管理与价值挖掘的核心枢纽,整合分散数据资源,构建统一的数据管理与服务体系。本数据中台产品涵盖数据可视化、数据建设、数据治理、数据采集开发和系统管理五大平台,以丰富且强大的功能模…...
第四章-初始化Direct3D
首先我们需要一个错误检测和抛出机制 inline std::string ToString(const HRESULT& result) {char buffer[256];sprintf_s(buffer, "error code : 0x%08X\n", result);return std::string(buffer); }class MyException : public std::runtime_error { public:My…...
实操3:6位数码管
文章目录 文章介绍仿真图原来的仿真代码教学用开发板段选和位选对应引脚思考题实物图 文章介绍 对应“案例5_3: 6位数码管显示0或者1【静态显示】” 跳转链接 要求:实现开发板的6位数码管同时显示0或者1 仿真图 原来的仿真代码 #include<reg52.h> // 头文件…...
常识补充(NVIDIA NVLink技术:打破GPU通信瓶颈的革命性互联技术)
文章目录 **引言:为什么需要NVLink?**1. NVLink技术概述1.1 什么是NVLink?1.2 NVLink的发展历程 2. NVLink vs. PCIe:关键对比2.1 带宽对比2.2 延迟对比 3. NVLink的架构与工作方式3.1 点对点直连(P2P)3.2 …...