C++技能系列( 9 ) - 如何实现线程池【详解】

news2024/10/6 10:36:35

系列文章目录

C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
C++技能系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

如何实现线程池

  • 系列文章目录
  • 一、要实现高效的线程池,可以考虑以下几点
  • 二、实现线程池可以按照以下步骤进行
  • 三、简单的C++线程池代码示例

C++线程池推荐一款基于boost编写的源码库:http://threadpool.sourceforge.net

一、要实现高效的线程池,可以考虑以下几点

  • 控制线程数量: 线程池的大小应该根据系统资源状况和任务量来设置。 太少的线程会导致任务被阻塞,太多的线程则会消耗过多的系统资源。可以使用固定大小的线程池、可缓存的线程池或定时器线程池等方式来进行控制。

  • 任务队列管理: 线程池应该有一个任务队列,用于存放等待执行的任务。 可以使用有界队列或无界队列来管理任务。有界队列可以控制任务的数量,而无界队列则可以接受任意数量的任务,但可能会导致内存溢出。

  • 线程调度策略: 线程池应该有一个合适的线程调度策略,如先进先出、优先级等。可以使用线程池的预定义实现,或自定义实现。

  • 线程错误处理: 线程池应该有一个错误处理机制,用于捕获线程执行过程中可能出现的异常,避免导致整个线程池崩溃。 可以使用try-catch语句或其他异常处理机制来处理异常。

  • 监控和调优: 线程池应该有一个监控和调优机制,用于实时监控线程池的状态和性能,并进行相应的调整。 可以使用监控工具、性能分析工具等来进行监控和调优。

通过合理的设置线程池的大小、任务队列的管理、线程调度策略、错误处理机制和监控调优,可以实现高效的线程池,提高程序的并发性能和资源利用率。

二、实现线程池可以按照以下步骤进行

(1)确定线程池的基本参数: 包括线程池大小、任务队列大小、拒绝策略等。可以根据实际需求来设置这些参数。

(2)创建一个任务队列: 用于存放待执行的任务。可以使用队列数据结构,如ArrayBlockingQueue、LinkedBlockingQueue等。

(3)创建线程池类: 定义一个线程池类,包括线程池的初始化、提交任务、执行任务、关闭等方法。可以使用ThreadPoolExecutor类来实现线程池。

(4)初始化线程池: 在线程池类中,提供一个初始化方法,该方法会根据线程池大小创建固定数量的线程,并将它们放入空闲线程池中。

(5)提交任务: 线程池类提供一个提交任务的方法,用于向任务队列中添加待执行的任务。可以通过调用线程池类的execute方法来实现任务的提交。

(6)执行任务: 线程池会自动从任务队列中获取任务,并将其分配给空闲的线程来执行。任务执行完成后线程会返回到线程池中,等待下一个任务。

(7)关闭线程池: 线程池类提供一个关闭方法,用于停止线程池的运行。线程池在关闭时会等待所有任务执行完毕,然后终止所有线程。

(7)错误处理和监控: 可以在线程池中添加错误处理逻辑,捕获任务执行过程中的异常,避免线程池崩溃。同时,可以添加监控机制,实时监控线程池的状态和性能。

根据上述步骤,可以自定义一个线程池类,实现线程池的功能。在实际使用时,根据具体需求来设置线程池的参数和调优线程池的性能。

三、简单的C++线程池代码示例

该示例中的ThreadPool类实现了一个简单的线程池,包括线程的创建、任务的提交、执行和线程池的关闭等功能。在主函数中使用线程池提交了10个任务,每个任务输出自己的编号和执行它的线程ID。在执行完所有任务之后,程序等待2秒后退出。

请注意,该示例代码只是一个搞笑的演示,可能不具备线程安全和实际应用的一些重要细节,请勿用于实际生产环境。在实际使用线程池时,需要考虑更多的线程同步、任务拆分和异常处理等问题。

#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>

class ThreadPool {
public:
    ThreadPool(int numThreads) : stop(false) {
        for (int i = 0; i < numThreads; ++i) {
            threads.emplace_back(std::thread([this](){
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(queueMutex);
                        condition.wait(lock, [this]{ return stop || !tasks.empty(); });
                        if (stop && tasks.empty()) {
                            return;
                        }
                        task = std::move(tasks.front());
                        tasks.pop();
                    }
                    task();
                }
            }));
        }
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            stop = true;
        }
        condition.notify_all();
        for (auto& thread : threads) {
            thread.join();
        }
    }

    template <typename FuncType>
    void submit(FuncType f) {
        {
            std::unique_lock<std::mutex> lock(queueMutex);
            tasks.emplace([f]() { f(); });
        }
        condition.notify_one();
    }

private:
    std::vector<std::thread> threads;
    std::queue<std::function<void()>> tasks;
    std::mutex queueMutex;
    std::condition_variable condition;
    bool stop;
};

int main() {
    ThreadPool pool(4);
    for (int i = 0; i < 10; ++i) {
        pool.submit([i]() {
            std::cout << "Task " << i << " executed by thread " << std::this_thread::get_id() << std::endl;
        });
    }
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 等待所有任务执行完
    return 0;
}
  • 使用std::thread::hardware_concurrency()来确定线程池中的线程数量,通常与处理器内核数相等,以充分利用系统资源。

  • 使用std::function作为任务类型,可以接受任意可调用对象,使用Lambda表达式封装具体任务。

  • 使用std::queue作为任务队列,通过std::mutex和std::condition_variable实现线程同步和互斥。

  • 通过条件变量std::condition_variable的wait()和notify_one()来控制线程的挂起和唤醒。

推荐几篇博文:

轻松掌握C++线程池:从底层原理到高级应用
https://zhuanlan.zhihu.com/p/636156144
https://blog.csdn.net/xyygudu/article/details/128767928

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1083703.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

室内渲染的艺术:室内渲染的灵魂!

在一个寒冷的冬日&#xff0c;当你走进一个温暖舒适的房间&#xff0c;是否曾想过这个房间的渲染效果是如何实现的呢&#xff1f;室内渲染作为一种视觉表现技术&#xff0c;能够将平面的设计转化为真实的三维场景&#xff0c;让人们更好地感受到空间的美感和舒适度。随着科技的…

Endnote 用户自定义Field

当EndNote自带的Field无法满足需求时&#xff0c;EndNote有8个可供用户自定义的Field&#xff08;Custom1-Custom8&#xff09;。我们可自定义其在题录编辑区及文献题录列表区中的名字。以改Custom3至“是否需要深入阅读”Field为例&#xff1a;步骤如下&#xff1a; Edit→Pre…

微信小程序 js中写一个px单位转rpx单位的函数

大家写东西自然还是会比较喜欢用rpx 但是 事实证明 在js中 还是px好用 因为很多单位交互的函数还是只返回px单位的 理论上将 750 rpx 是整个屏幕的宽度 那么 我们可以这样写一个函数 pxToRpx(px) {//获取整个屏幕的宽度单位 pxlet screenWidth wx.getSystemInfoSync().scree…

libncurses.so.5: cannot open shared object file: No such file or directory解决办法

最近在安装mysql的时候碰到这个问题&#xff0c;由此记录一下 mysql: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory解决办法 yum install ncurses-compat-libs

程序员内心独白:注释,爱恨交加,双标难舍

程序员对代码注释可以说是又爱又恨又双标……你是怎么看待程序员不写注释这一事件的呢&#xff1f; 方向一&#xff1a;分享你的观点和故事 对公司好的方面&#xff1a; 从程序员的角度来看&#xff0c;注释对于代码的可读性和可维护性非常重要。注释可以让其他开发者更容易理…

C语言之通讯录的实现篇

目录 test.c 主菜单menu 创建通讯录con 初始化通讯录InitContact 增加个人信息AddContact 展示个人信息ShowContact 删除个人信息DelContact 查找个人信息SearchContact 修改个人信息ModifyContact test.c总代码 contact.h 头文件包含 PeoInfo_个人信息的设置声…

基于PTP的同步时钟同步

基于PTP的同步时钟同步 编辑搜图 请点击输入图片描述&#xff08;最多18字&#xff09; ​本设计采用PTP (Precision Time Protocol)协议&#xff0c;来实现同步时间。PTP是一种精确测量和控制系统的网络协议&#xff0c;用于同步分布式系统中的各种设备和服务器的时间。 首先…

Maxon Cinema 4D 2024:创造无限可能,激发你的创造力

在视觉效果和3D建模领域&#xff0c;Maxon的Cinema 4D一直以其卓越的性能和创新的功能引领着时代潮流。今天&#xff0c;我们很高兴地宣布推出最新版本——Maxon Cinema 4D 2024&#xff08;C4D 2024&#xff09;&#xff0c;它将再次提升行业标准&#xff0c;为设计师提供更强…

SVN提交项目时,出现了这样的提示:“XXX“ is scheduled for addition, but is missing。

原因是&#xff1a;之前用SVN提交过的文件/文件夹&#xff0c;被标记为"addition"状态&#xff0c;等待被加入到仓库。虽然你把这个文件删除了&#xff0c;SVN提交的时候还是会尝试提交这个文件&#xff0c;所以就会提示&#xff1a;"but is missing"。解决…

科技资讯|9月新能源汽车零售74.3万辆,充电桩迎来发展高峰

据中国乘联会发布的初步数据&#xff0c;中国 9 月份乘用车市场零售 202.8 万辆&#xff0c;同比增长 6%&#xff0c;环比增 6%。今年以来&#xff0c;我国乘用车市场累计零售 1,524 万辆&#xff0c;同比增长 2%。 乘联会预计&#xff0c;9 月份新能源车市场零售 74.3 万辆&a…

​电子商务新宠电商独立站成功案例解析|抢占市场巅峰:成功打造日本跨境电商独立站攻略! ​

日本离中国只有690公里&#xff0c;时差仅一个小时。距离和便捷的物流是日本跨境电商最具天然的优势&#xff0c;但除了这种天然优势外&#xff0c;日本还有哪些优势不容忽视&#xff1f;无论是独立站还是乐天、雅虎、日亚&#xff0c;都要遵循一个国家的消费习惯&#xff0c;制…

更新 | 持续开源迅为RK3568驱动指南第十二篇-GPIO子系统

《iTOP-RK3568开发板驱动开发指南》更新&#xff0c;本次更新内容对应的是驱动&#xff08;第十二期_GPIO子系统-全新升级&#xff09;视频&#xff0c;后续资料会不断更新&#xff0c;不断完善&#xff0c;帮助用户快速入门&#xff0c;大大提升研发速度。 文档教程更新至第十…

【翻译】增长秘笈,如何让你的开源项目Star数快速增长

TL;DR &#xff08;前言&#xff09; 本文翻译自 https://star-history.com/blog/playbook-for-more-github-stars&#xff0c;尽可能遵照原文&#xff0c;部分内容做少许改动。 我和我的团队最近推出了一个面向开发者的开源工具。这是我第一次推广一个开源工具。很难找到有意…

ES相关面试问题整理

索引模板了解么 索引模板&#xff0c;一种复用机制&#xff0c;就像一些项目的开发框架如 Laravel 一样&#xff0c;省去了大量的重复&#xff0c;体力劳动。当新建一个 Elasticsearch 索引时&#xff0c;自动匹配模板&#xff0c;完成索引的基础部分搭建。 模板定义&#xf…

印尼封锁TikTok Shop后,数字商业将何去何从?

近年来&#xff0c;TikTok已成为全球范围内备受欢迎的短视频平台&#xff0c;它的崛起改变了用户的娱乐方式&#xff0c;也为商家提供了一个全新的数字营销平台。 然而&#xff0c;最近印尼政府宣布封锁TikTok Shop&#xff0c;理由是平台上存在虚假广告和欺诈行为。这一决定引…

跳槽阿里,面试被虐惨了

1、八股文几乎全背熟&#xff0c;谁能想到最后问的全是JVM&#xff0c;一下给我问懵了&#xff0c;当场就挂了&#xff01; 2、曾经的我很不屑JVM&#xff0c;后来我逐帧学习&#xff01; 3、现在竞争激烈&#xff0c;甭管什么厂&#xff0c;都要问点JVM&#xff01; 最近有…

sonarqube 代码质量检测

官方文档 1.安装 我安装的是 sonarqube-10.2 需要jdk17的环境请先安装 jdk17 下载sonarqube-10.2安装包 直接解压、运行启动脚本 sonarqube-10.2.1.78527\bin\windows-x86-64\StartSonar.batsonarqube访问端口&#xff1a;9000 http://localhost:9000 2.项目改造 2.1 修改…

【TensorFlow2 之011】TF 如何使用数据增强提高模型性能?

一、说明 亮点&#xff1a;在这篇文章中&#xff0c;我们将展示数据增强技术作为提高模型性能的一种方式的好处。当我们没有足够的数据可供使用时&#xff0c;这种方法将非常有益。 教程概述&#xff1a; 无需数据增强的训练什么是数据增强&#xff1f;使用数据增强进行训练可视…

Excel 中使用数据透视图进行数据可视化

使用数据透视表&#xff08;PivotTable&#xff09;是在Excel中进行数据可视化的强大工具。下面将提供详细的步骤来使用数据透视表进行数据可视化。 **步骤一&#xff1a;准备数据** 首先&#xff0c;确保你有一个包含所需数据的Excel表格。数据应该按照一定的结构和格式组织…

4.js中next()方法与prev()方法使用

我们可以选择某个DOM元素进行获取和操作&#xff0c;但是有时候我们在操作某个元素的时候&#xff0c;也要对它相邻的的元素进行获取或是操作&#xff0c;那我们该如何去做呢&#xff0c;今天记录一个获取某个元素的相邻的上一个元素或相邻的下一个元素 js中的next()方法 next…