C++ 入门第25天:线程池(Thread Pool)基础
往期回顾:
C++ 学习第22天:智能指针与异常处理-CSDN博客
C++ 入门第23天:Lambda 表达式与标准库算法入门-CSDN博客
C++ 入门第24天:C++11 多线程基础-CSDN博客
C++ 入门第25天:线程池(Thread Pool)基础
前言
线程池 是一种高效的线程管理机制,通过复用一组线程来处理多个任务,避免频繁创建和销毁线程的开销。线程池在高并发场景中尤为重要,是现代程序开发中提升性能和资源利用率的重要工具。
今天,我们将学习线程池的基础知识,并实现一个简单的线程池。
1. 什么是线程池?
线程池的核心思想是提前创建一组线程,将任务放入队列中,线程从队列中取出任务并执行。当任务完成后,线程不会销毁,而是返回池中等待下一个任务。
线程池的优点:
- 降低线程创建和销毁的开销。
- 控制线程的并发数量,避免资源过度消耗。
- 提高任务处理效率。
2. 线程池的基本结构
线程池的实现主要包括以下几个部分:
- 任务队列:存储需要执行的任务。
- 工作线程:从任务队列中取出任务并执行。
- 任务提交接口:提供给用户提交任务的功能。
3. 使用 std::async 实现简单线程池
std::async 是 C++11 提供的一种异步任务工具,可以用来实现简单的线程池。
示例代码
#include <iostream>
#include <future>
#include <vector>
using namespace std;// 一个简单的任务函数
int task(int n) {cout << "Task " << n << " is running in thread " << this_thread::get_id() << endl;return n * n;
}int main() {// 存储 future 对象的容器vector<future<int>> results;// 提交多个任务for (int i = 1; i <= 5; i++) {results.push_back(async(launch::async, task, i));}// 获取任务的执行结果for (auto &result : results) {cout << "Result: " << result.get() << endl;}return 0;
}
输出结果(线程 ID 可能不同):
Task 1 is running in thread 12345
Task 2 is running in thread 12346
Task 3 is running in thread 12347
Task 4 is running in thread 12348
Task 5 is running in thread 12349
Result: 1
Result: 4
Result: 9
Result: 16
Result: 25
4. 手动实现线程池
为了更深入理解线程池,我们可以手动实现一个简单的线程池。
4.1 线程池的代码实现
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>
using namespace std;class ThreadPool {
public:ThreadPool(size_t num_threads);~ThreadPool();// 提交任务到线程池template <class F, class... Args>auto enqueue(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type>;private:vector<thread> workers; // 工作线程queue<function<void()>> tasks; // 任务队列mutex queue_mutex; // 互斥锁condition_variable condition; // 条件变量bool stop; // 停止标志
};// 构造函数:创建指定数量的线程
ThreadPool::ThreadPool(size_t num_threads) : stop(false) {for (size_t i = 0; i < num_threads; ++i) {workers.emplace_back([this] {while (true) {function<void()> task;{unique_lock<mutex> lock(this->queue_mutex);this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });if (this->stop && this->tasks.empty()) return;task = move(this->tasks.front());this->tasks.pop();}task();}});}
}// 提交任务到线程池
template <class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) -> future<typename result_of<F(Args...)>::type> {using return_type = typename result_of<F(Args...)>::type;auto task = make_shared<packaged_task<return_type()>>(bind(forward<F>(f), forward<Args>(args)...));future<return_type> res = task->get_future();{lock_guard<mutex> lock(queue_mutex);if (stop) throw runtime_error("enqueue on stopped ThreadPool");tasks.emplace([task]() { (*task)(); });}condition.notify_one();return res;
}// 析构函数:停止所有线程
ThreadPool::~ThreadPool() {{lock_guard<mutex> lock(queue_mutex);stop = true;}condition.notify_all();for (thread& worker : workers) {if (worker.joinable()) worker.join();}
}
4.2 使用线程池
#include <iostream>
#include "ThreadPool.h" // 假设前面的代码在 ThreadPool.h 中
using namespace std;int main() {// 创建一个包含 4 个线程的线程池ThreadPool pool(4);// 提交任务并获取结果auto result1 = pool.enqueue([](int a, int b) { return a + b; }, 2, 3);auto result2 = pool.enqueue([](int n) { return n * n; }, 5);cout << "Result1: " << result1.get() << endl;cout << "Result2: " << result2.get() << endl;return 0;
}
输出结果:
Result1: 5
Result2: 25
结语
以上就是 C++ 11 多线程中线程池的基础知识点了。线程池是现代多线程编程的重要工具,线程池的原理:通过复用线程和任务队列,提高性能和资源利用率。std::async 的简单实现:快速实现异步任务处理。同时我们手动从零开始实现了一个功能完整的线程池。线程池可以大幅提升程序的效率,但在实际使用中,需要注意线程的同步和资源管理问题。
都看到这里了,点个赞再走呗朋友~
加油吧,预祝大家变得更强!
相关文章:
C++ 入门第25天:线程池(Thread Pool)基础
往期回顾: C 学习第22天:智能指针与异常处理-CSDN博客 C 入门第23天:Lambda 表达式与标准库算法入门-CSDN博客 C 入门第24天:C11 多线程基础-CSDN博客 C 入门第25天:线程池(Thread Pool)基础 前…...
微信小程序中的 storage(本地存储)和内存是两个完全不同的存储区域
这是一个非常关键且容易混淆的概念 既然 this.globalData.appId appId 是将 appId 存储在内存中,为什么微信小程序中的 wx.getStorage 和 wx.setStorage(本地存储)中没有 appId,并且您提出了一个非常重要的疑问:stor…...
WLAN基本原理与配置
一、WLAN概述 二、WLAN的基本概念 AC与Fit AP的组网架构: 1.二层组网 AC和Fit AP在一个广播域中 2.三层组网 AC和Fit AP需要跨三层通信 CAPWAP(无线接入点控制和配置协议): 该协议定义了如何对AP进行管理、业务配置&#…...
KaliLinux 2022.1安装和相关配置
一、安装系统和设置中文 (一)下载安装KaliLInux2022.1 以直接下载虚拟机映像文件为例,下载地址:https://www.kali.org/get-kali/#kali-virtual-machines,下载完成后直接解压,再用VMware打开后开机&#x…...
HarmonyOS开发:ArkTS初识
ArkTS基本语法 ArkTS语言简介 ArkTS是鸿蒙生态的应用开发语言。基本语法风格与TypeScript(简称TS)相似,在TS的生态基础上进一步扩展,继承了TS的所有特性,是TS的超集。 基本语法概述 扩展能力 基础语法:…...
Unity的四种数据持久化方式
目录 什么是数据持久化 数据持久化之PlayerPrefs 概述 API及用法 电脑中存放的位置 优缺点 主要用处 封装PlayerPrefs 数据持久化之XML XML是什么 读取XML信息 C#读取XML的方法有几种 读取xml文件信息 读取元素和属性信息 总结 写入XML信息 选择存储目录 存储…...
机器学习笔记 - 单幅图像深度估计的最新技术
1、深度估计简述 单眼深度估计是一项计算机视觉任务,AI 模型从单个图像中预测场景的深度信息。模型估计场景中对象从一个照相机视点的距离。单目深度估计已广泛用于自动驾驶、机器人等领域。深度估计被认为是最困难的计算机视觉任务之一,因为它要求模型理解对象及其深度信息之…...
Postman接口测试02|接口用例设计
目录 六、接口用例设计 1、接口测试的测试点(测试维度) 1️⃣功能测试 2️⃣性能测试 3️⃣安全测试 2、设计方法与思路 3、单接口测试用例 4、业务场景测试用例 1️⃣分析测试点 2️⃣添加员工 3️⃣查询员工、修改员工 4️⃣删除员工、查询…...
C#语言的学习路线
C#语言的学习路线 C#(读作“C Sharp”)是一种由微软开发的现代编程语言,具有强大的功能和灵活性,广泛应用于桌面应用程序、Web开发、游戏开发以及企业级应用等多个领域。无论你是编程新手还是有一定基础的开发者,掌握…...
双目的一些文章学习
文章1 PSMNet https://arxiv.org/pdf/1803.08669PSMNet文章博客PSMNet文章中牵涉到的一些知识,空洞卷积,SPPNet网络,计算视差时用soft argmin代替argmin文章中引入了空洞卷积和SPPNet网络来融合多尺度的信息,又引入3D卷积来增加模…...
开源模型应用落地-qwen2-7b-instruct-LoRA微调合并-ms-swift-单机单卡-V100(十三)
一、前言 本篇文章将使用ms-swift去合并微调后的模型权重,通过阅读本文,您将能够更好地掌握这些关键技术,理解其中的关键技术要点,并应用于自己的项目中。 二、术语介绍 2.1. LoRA微调 LoRA (Low-Rank Adaptation) 用于微调大型语言模型 (LLM)。 是一种有效的自适应策略,…...
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
目录😋 任务描述 相关知识 一、类的声明和使用 1. 类的声明基础 2. 类的访问控制 3. 类的使用 二、类的声明和对象的声明 1. 类声明中的函数定义 2. 对象声明的多种方式 三、构造函数和析构函数的执行过程 1. 构造函数 2. 析构函数 实验步骤 测试说明…...
性能测试05|JMeter:分布式、报告、并发数计算、性能监控
目录 一、JMeter分布式 1、应用场景 2、原理 3、分布式相关注意事项 4、分布式配置与运行 二、JMeter报告 1、聚合报告 2、HTML报告 三、并发用户数(线程数)计算 四、JMeter下载第三方插件 五、性能监控 1、Concurrency Thread Group 线程组…...
关于Java面试题大全网站无法访问的解决方案
如果Java面试题大全网站无法访问,你仍然可以通过以下渠道获取高质量的Java面试题资源: 1. 国内网站 牛客网: 网址:https://www.nowcoder.com/特点:提供大量Java面试题和在线编程练习,适合刷题和模拟面试。推…...
CSS进阶和SASS
目录 一、CSS进阶 1.1、CSS变量 1.2、CSS属性值的计算过程 1.3、做杯咖啡 1.4、下划线动画 1.5、CSS中的混合模式(Blending) 二、SASS 2.1、Sass的颜色函数 2.2、Sass的扩展(extend)和占位符(%)、混合(Mixin) 2.3、Sass的数学函数 2.4、Sass的模块化开发 2.5、Sass…...
SwiftUI 撸码常见错误 2 例漫谈
概述 在 SwiftUI 日常撸码过程中,头发尚且还算茂盛的小码农们经常会犯这样那样的错误。虽然犯这些错的原因都很简单,但有时想要快速准确的定位它们却并不容易。 况且这些错误还可能在模拟器和 Xcode 预览(Preview)表现的行为不甚…...
JavaScript系列(9)-- Set数据结构专题
JavaScript Set数据结构专题 🎲 在前八篇文章中,我们探讨了JavaScript的语言特性、ECMAScript标准、引擎工作原理、数值类型、字符串处理、Symbol类型、Object高级特性和Array高级操作。今天,让我们深入了解JavaScript中的Set数据结构。Set是…...
开发培训-慧集通(iPaaS)集成平台脚本开发Groovy基础培训视频
Groovy是一种基于Java虚拟机(JVM)的敏捷开发语言,结合了Python、Ruby和Smalltalk的许多强大特性。它旨在提高开发者的生产力,通过简洁、熟悉且易于学习的语法,Groovy能够与Java代码无缝集成,并提供强大…...
【软考网工笔记】计算机基础理论与安全——网络规划与设计
HFC 混合光纤同轴电缆网 HFC: Hybrid Fiber - Coaxial 的缩写,即混合光纤同轴电缆网。是一种经济实用的综合数字服务宽带网接入技术。 HFC 通常由光纤干线、同轴电缆支线和用户配线网络三部分组成,从有线电视台出来的节目信号先变成光信号在干线上传输…...
【设计模式】 基本原则、设计模式分类
设计模式 设计模式是软件工程中的一种通用术语,指的是针对特定问题的经过实践验证的解决方案。设计模式并不是最终的代码实现,而是描述了如何解决某一类问题的思路和方法。 如果熟悉了设计模式,当遇到类似的场景,我们可以快速地…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
