线程池学习

github看到一个项目(GitHub - markparticle/WebServer: C++ Linux WebServer服务器),内部使用的一个线程池看着不错,拿来学习一下。

/** @Author       : mark* @Date         : 2020-06-15* @copyleft Apache 2.0*/ #ifndef THREADPOOL_H
#define THREADPOOL_H#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>
#include <functional>
class ThreadPool {
public:explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared<Pool>()) {assert(threadCount > 0);for(size_t i = 0; i < threadCount; i++) {std::thread([pool = pool_] {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->isClosed) break;else pool->cond.wait(locker);}}).detach();}}ThreadPool() = default;ThreadPool(ThreadPool&&) = default;~ThreadPool() {if(static_cast<bool>(pool_)) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->isClosed = true;}pool_->cond.notify_all();}}template<class F>void AddTask(F&& task) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->tasks.emplace(std::forward<F>(task));}pool_->cond.notify_one();}private:struct Pool {std::mutex mtx;std::condition_variable cond;bool isClosed;std::queue<std::function<void()>> tasks;};std::shared_ptr<Pool> pool_;
};#endif //THREADPOOL_H

1,先看下 私有变量。

struct Pool {std::mutex mtx;std::condition_variable cond;bool isClosed;std::queue<std::function<void()>> tasks;};
std::shared_ptr<Pool> pool_;

一个结构体 Pool 将用到的变量,全部包含进去。

mtx 一个锁,用于加入,取出任务。

cond 信号量,用于线程间同步。

isClosed 线程池退出的标志。

tasks 任务队列,存放所有需要在线程中执行的任务。

pool_ 智能指针,管理所有资源。

2,构造函数

(1),默认开启8个线程(size_t threadCount = 8),并在初始化列表中  初始化pool_对象(std::make_shared<Pool>())

(2),循环启动每个线程

for(){std::thread({//todo}).detach();
}

(3),加锁  确保 ,各个线程对 任务队列(tasks) 不产生竞争,因为添加任务,取任务都要操作这个队列。

std::unique_lock<std::mutex> locker(pool->mtx);

(4),单独看一个线程。

首先判断任务队列是否为空,为空 则利用信号量阻塞当前线程。

else pool->cond.wait(locker);

如果线程池是退出状态,则跳出当前循环,当前线程也会退出。

else if(pool->isClosed) break;

如果任务队列不为空,则取出第一个任务,队列减1,然后解锁,执行任务,再加锁。

auto task = std::move(pool->tasks.front());
pool->tasks.pop();
locker.unlock();
task();
locker.lock();

std::move 用于移动语义,允许在不复制内存的情况下转移资源的所有权。这段代码之后,相当于8个线程,从任务队列tasks 中抢任务,抢到一个执行一个。比如A线程 抢到了任务1,任务1 在执行中过程中,由于队列处于未加锁状态,那B线程,就可以继续抢任务2。

3,添加任务

std::forward ,在一个函数中将参数以原始的形式传递给另一个函数,同时保持其值类别(lvalue 或 rvalue)和 const 修饰符。

这里将task 添加到 任务队列 tasks中。并且利用locker 进行保护。这里添加完成之后,上述的8个线程就会从这个任务队列中抢任务,然后执行。

    template<class F>void AddTask(F&& task) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->tasks.emplace(std::forward<F>(task));}pool_->cond.notify_one();}

3,销毁

将isClosed 标志置为false,并通知所有线程继续执行,防止因为任务队列为空,造成阻塞无法退出。在上述循环中,检测到isClosed 为fasel,则while循环退出,线程退出。

    ~ThreadPool() {if(static_cast<bool>(pool_)) {{std::lock_guard<std::mutex> locker(pool_->mtx);pool_->isClosed = true;}pool_->cond.notify_all();}}

5,使用

构造完ThreadPool 之后,直接调用AddTask ,将任务传入其中即可。

std::bind  用于创建一个可调用对象,将其与特定的参数绑定在一起。

 在C++11 之下,封装一个线程池 还是很优雅的。

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

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

相关文章

Windows系统搭建VisualSVN并结合内网穿透实现远程访问本地服务

文章目录 前言1. VisualSVN安装与配置2. VisualSVN Server管理界面配置3. 安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4. 固定公网地址访问 前言 SVN 是 subversion 的缩写&#xff0c;是一个开放源代码的版本控制系统…

Spring 事务常见错误(上)

通过上一章的学习&#xff0c;我们了解了 Spring Data 操作数据库的一些常见问题。这一章我们聊一聊数据库操作中的一个非常重要的话题——事务管理。 Spring 事务管理包含两种配置方式&#xff0c;第一种是使用 XML 进行模糊匹配&#xff0c;绑定事务管理&#xff1b;第二种是…

洗澡、泡脚真的能养生? 皮肤科医生来科普

现如今人们越来越注重健康与养生&#xff0c;除了枸杞、生姜等食补外&#xff0c;各种保健方法和保健产品也层出不穷&#xff0c;还有泡脚、洗凉水澡等养生延缓衰老的方式也广泛流行&#xff0c;那么泡脚与洗凉水澡真的有用吗?西安国际医学中心医院皮肤科主任高鹏程特意进行了…

Timeplus-proton流处理器调研

概念 Timeplus是一个流处理器。它提供强大的端到端功能&#xff0c;利用开源流引擎Proton来帮助数据团队快速直观地处理流数据和历史数据&#xff0c;可供各种规模和行业的组织使用。它使数据工程师和平台工程师能够使用 SQL 释放流数据价值。 Timeplus 控制台可以轻松连接到不…

女性三八节礼物攻略:她无法抗拒的五大礼物

随着春风的温柔拂面&#xff0c;我们即将迎来一年一度的三八国际妇女节。这个特别的日子&#xff0c;不仅是对女性贡献的认可和庆祝&#xff0c;也是向我们生命中的女性表达感激和爱意的绝佳时机。在这个充满温馨和敬意的时刻&#xff0c;我们常常在思考&#xff0c;如何用一份…

elementUI el-table中的对齐问题

用elementUI时&#xff0c;遇到了一个无法对齐的问题&#xff1a;代码如下&#xff1a; <el-table :data"form.dataList" <el-table-column label"验收结论" prop"checkResult" width"200"> <template slot-sco…

揭秘!Excel如何成为职场中的价值创造利器

文章目录 一、Excel在生产力提升中的作用二、Excel在创造价值方面的应用案例三、Excel实用技巧分享四、Excel与其他工具的协同应用五、Excel学习的建议与展望《Excel函数与公式应用大全》亮点内容简介作者简介目录 在当今信息爆炸的时代&#xff0c;数据处理和分析能力已成为职…

AI智能分析网关V4智慧商场方案,打造智慧化商业管理生态

AI智能视频检测技术在商场楼宇管理中的应用越来越广泛。通过实时监控、自动识别异常事件和智能预警&#xff0c;这项技术为商场管理提供了更高效、更安全的保障。今天我们以TSINGSEE青犀视频AI智能分析网关为例&#xff0c;给大家介绍一下AI视频智能分析技术如何应用在商场楼宇…

抢单情况下的均衡分配机制

背景&#xff1a; 1、工单有多种类型。 2、客户提交工单。 3、不同客服受理不同类型工单&#xff0c;受理工单类型存在交叉。 4、按照类型维度实现均衡分配。 方案&#xff1a; 1、为每种类型创建一个工单池&#xff0c;使用队列&#xff0c;左进右出&#xff1b;客户提交…

将所有字母转化为该字母后的第三个字母,即A->D,B->E

//编写加密程序&#xff0c;规则&#xff1a;将所有字母转化为该字母后的第三个字母&#xff0c;即A->D,B->E,C->F,…Y->B,Z->C //小写字母同上&#xff0c;其他字符不做转化。输入&#xff1a;I love 007 输出&#xff1a;L oryh 007 代码&#xff1a; #inc…

配置MMDetection的solov2攻略整理

目录 一、MMDetection 特性 常见用法 二、ubuntu20.04配置solov2 三、Windows11配置solov2 一、MMDetection MMDetection是一个用于目标检测的开源框架&#xff0c;由OpenMMLab开发和维护。它提供了丰富的预训练模型和模块&#xff0c;可以用于各种目标检测任务&#xff…

redis的基本数据类型(一)

redis的基本数据类型 1、redis1.1、数据库分类1.2、NoSQL分类1.3、redis简介1.4、redis应用1.5、如何学习redis 2、redis的安装2.1、Windows安装2.2.1、客户端redis管理工具 2.2、Linux安装&#x1f525;2.2.1、redis核心文件2.2.2、启动方式2.2.3、redis桌面客户端1、redis命令…

Python进阶学习:Pickle模块--dump()和load()的用法

Python进阶学习&#xff1a;Pickle模块–dump()和load()的用法 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您…

ASO 对App产品性能的影响

可发现性 拥有出色的App还不足以让人们发现它&#xff0c;ASO技术通过提高搜索排名来增强App的可发现性。当用户可以在搜索结果中轻松找到应用程序时&#xff0c;那么下载和成功的潜力就会飙升。 设定期望 实施有效的应用商店优化不仅可以为潜在用户建立正确的期望&#xf…

东方通 | 基于TongWeb中间件适配改造实战

东方通 一、东方通[Tong Web] 简介 ​为了方便地开发、部署、运行和管理Internet上基于三层/多层结构的应用&#xff0c;需要以基于组件的底层技术为基础&#xff0c;规划一个整体的应用框架&#xff0c;提供相应的支撑平台&#xff0c;作为Internet应用的基础设施&#xff0…

每日一类:Qt GUI开发的基石《QWidget》

深入探索QWidget&#xff1a;Qt GUI开发的基石 在Qt框架中&#xff0c;QWidget类扮演着构建图形用户界面&#xff08;GUI&#xff09;的基础角色。它不仅提供了窗口的基本功能&#xff0c;还允许开发者通过继承和定制来创建各式各样的用户界面元素。本文将详细介绍QWidget的关…

白酒:传统酿造工艺与现代科技相结合的创新实践

在云仓酒庄豪迈白酒的生产过程中&#xff0c;传统酿造工艺与现代科技的结合是推动产业发展的重要动力。云仓酒庄作为一家注重创新与实践的酒庄&#xff0c;在这方面进行了许多有益的探索和尝试。 首先&#xff0c;传统酿造工艺是云仓酒庄豪迈白酒的灵魂。在长期的生产实践中&am…

抽丝剥茧!API在互联网金融领域里大显身手:深度解锁三大创新应用场景

&#x1f680; 引言 有这么一位幕后高手&#xff0c;它不显山露水却能牵动整个互联网金融江湖的脉搏&#xff0c;它在无形中编织数据网络&#xff0c;如同枢纽般连通各方资源&#xff0c;在静默中推动创新进程&#xff0c;这就是大名鼎鼎的API&#xff08;应用程序接口&#x…

基于ssm学生学籍管理系统设计与实现+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

C语言:指针(二)

目录 1.数组名的理解2.使用指针访问数组3.一维数组传参的本质4.二级指针5.指针数组6.字符指针变量7.数组指针变量8.二维数组传参的本质9.函数指针变量10.函数指针数组11.回调函数12.qsort函数13.使用回调函数模拟实现qsort函数 1.数组名的理解 int main() {int arr[] { 1,2,3…