base7. ThreadPool线程池类——生产者与消费者模型

2023-05-16

ThreadPool类图
在这里插入图片描述
数据成员:

MutexLock mutex_:一个MutexLock类型的互斥变量mutex_
Condition cond_:一个Condition类型的条件变量cond_
string name_:线程池的名称
boost::ptr_vector<muduo::Thread>threads_:消费者线程队列threads_
std::deque<task. >queue_:任务队列queue_,其中task为一个执行任务的函数,生产者线程在queue_添加任务,所有threads_共享queue_
bool running_:running_表示线程池是否处于运行状态

typedef

typedef boost::function<void ()> Task:基于对象编程的回调函数

成员函数:

explicit ThreadPool(const string& name = string()):构造函数
~ThreadPool():析构函数
void start(int numThreads):启动线程池,其中有numThreads个线程
void stop():关闭线程池
void run(const Task& f):将任务task添加到线程中的任务队列queue_
void runInThread():线程池中的线程要执行的函数
Task take():获取任务

ThreadPool.h

//线程池本质上也是一个生产者/消费者模型
#ifndef MUDUO_BASE_THREADPOOL_H
#define MUDUO_BASE_THREADPOOL_H

#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/Types.h>

#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/ptr_container/ptr_vector.hpp>

#include <deque>

//固定的线程池,线程池中的线程个数是固定的,不可以自动伸缩
namespace muduo
{

class ThreadPool : boost::noncopyable
{
 public:
  typedef boost::function<void ()> Task;

  explicit ThreadPool(const string& name = string());
  ~ThreadPool();
  //启动线程池,其中有numThreads个线程
  void start(int numThreads);
  //关闭线程池
  void stop();
  //在任务队列queue_中添加任务
  void run(const Task& f);

 private:
  //线程池中的线程要执行的函数
  void runInThread();
  //获取任务
  Task take();
  //一个MutexLock类型的互斥变量mutex_
  MutexLock mutex_;
  //一个Condition类型的条件变量cond_
  Condition cond_;
  //线程池的名称
  string name_;
  //消费者线程队列threads_
  boost::ptr_vector<muduo::Thread> threads_;
  //任务队列queue_,其中task为一个执行任务的函数,生产者线程在queue_添加任务
  std::deque<Task> queue_;
  //running_表示线程池是否处于运行状态
  bool running_;
};

}

#endif

ThreadPool.cc

#include <muduo/base/ThreadPool.h>

#include <muduo/base/Exception.h>

#include <boost/bind.hpp>
#include <assert.h>
#include <stdio.h>

using namespace muduo;

ThreadPool::ThreadPool(const string& name)
  : mutex_(),
    cond_(mutex_),
    name_(name),
    running_(false)
{
}

ThreadPool::~ThreadPool()
{
  if (running_)
  {
    stop();
  }
}

void ThreadPool::start(int numThreads)
{
  assert(threads_.empty());
  running_ = true;
  threads_.reserve(numThreads);
  //添加消费者线程
  for (int i = 0; i < numThreads; ++i)
  {
    char id[32];
    snprintf(id, sizeof id, "%d", i);
    threads_.push_back(new muduo::Thread(
          boost::bind(&ThreadPool::runInThread, this), name_+id));
    //启动runInThread函数
	threads_[i].start();
  }
}

void ThreadPool::stop()
{
  {
  MutexLockGuard lock(mutex_);
  running_ = false;
  //通知所有等待线程
  cond_.notifyAll();
  }
  for_each(threads_.begin(),
           threads_.end(),
           boost::bind(&muduo::Thread::join, _1));
}

//将任务task添加到线程中的任务队列queue_
void ThreadPool::run(const Task& task)
{
  //消费者线程队列threads_为空
  if (threads_.empty())
  {
	//直接执行
    task();
  }
  else
  {
    MutexLockGuard lock(mutex_);
    queue_.push_back(task);
	//通知take()函数,有任务task可以获取
    cond_.notify();
  }
}

ThreadPool::Task ThreadPool::take()
{
  MutexLockGuard lock(mutex_);
  // always use a while-loop, due to spurious wakeup
  while (queue_.empty() && running_)
  {
	//等待函数run()添加任务
    cond_.wait();
  }
  Task task;
  if(!queue_.empty())
  {
    task = queue_.front();
    queue_.pop_front();
  }
  return task;
}

//runInThread()函数调用take()获取任务task
void ThreadPool::runInThread()
{
  try
  {
    while (running_)
    {
	  //阻塞在此函数,消费者线程中的runInThread()函数调用take()获取任务task
      Task task(take());
      //任务task不为空,而执行任务task
	  if (task)
      {
        task();
      }
    }
  }
  catch (const Exception& ex)
  {
    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
    fprintf(stderr, "reason: %s\n", ex.what());
    fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
    abort();
  }
  catch (const std::exception& ex)
  {
    fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());
    fprintf(stderr, "reason: %s\n", ex.what());
    abort();
  }
  catch (...)
  {
    fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());
    throw; // rethrow
  }
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

base7. ThreadPool线程池类——生产者与消费者模型 的相关文章

  • U盘安装Windows10系统报错无法打开文件install.wim原因及解决办法

    1 现象描述 xff1a 毕业后买了一台联想Y7000P笔记本电脑用了一年左右 xff0c 换了工作后一直用的公司Mac笔记本 xff0c 就这样联想笔记本闲置几年再次使用时系统更新一下 xff0c 卡的要死就想重新安装一下系统 xff0c
  • Spring JPA native query 分页错误记录

    相信大家对SpringData JPA 自定义分页查询已经很熟悉了 xff0c 今天博主遇见了一个奇怪的问题 xff0c 记录下来 xff0c 跟大家分享 根据已经学习到的知识 xff0c 对于 64 Query nativeQuery 6
  • python 重复输出字符串

    阿里云大学人工智能学前小测验 Python测试 7 a 61 1 b 61 a 2 输出b的值为 A 1 B 2 C 11 D null 我选的答案是D xff0c 结果 答案是C xff0c 因为python可以通过str 2重复输出字符
  • socket中文乱码问题

    问题描述 xff1a 后端向前端发送中文 xff0c 前端显示正常 前端向后端发送中文 xff0c 后端显示乱码 解决 xff1a 前端js引入 最新版的 socket io js xff0c 不能使用socket io min js sp
  • python 将字符串小数 转换为 整型

    问题描述 xff1a 直接使用int函数将字符串类型的小数转换为 int型会报错 问题解决 xff1a 先转换为float型 xff0c 再转换为 int 型
  • MySQL binlog设置和查看命令

    目录 开启binlog重置命令查看binlog 开启binlog span class token comment 编辑模式进入 etc my cnf span span class token function vim span etc
  • kafka3.1 简介 (一)

    kafka3 1 简介 xff08 一 xff09 主要概念和术语事件流 xff08 Event streaming xff09 服务器 xff08 server xff09 与客户端 client serversclient 事件 xff
  • 作为一名普通的程序员,聊聊这四年的工作感悟

    之前有些小伙伴一直想听我分享更多有关我的工作内容的事情 xff0c 今天就来和大家分享一下 我是一名普通的程序员 xff0c 这四年来我的工作内容发生了哪些变化 xff0c 以及我有哪些感悟 我是16届的毕业生 xff0c 我的第一份工作是
  • js页面跳转的时候使用 post发送数据

    需求背景 页面跳转的时候需要带一些参数 xff0c 但是又不想让这些数据展示给用户 xff0c 所以需要使用post实现跳转 代码实现 span class token comment 点击进入项目详情页面 span window span
  • flask返回页面和数据,js获取数据

    flask 返回数据 span class token keyword if span request span class token punctuation span method span class token operator 6
  • git 将本地分支与远程分支关联

    需求背景 项目在远程新建了一个分支 xff0c 但是本地没有这个分支 xff0c 需要在本地开发完之后 xff0c 将最新的代码放到 远程分支上 问题一 xff1a 本地没有这个分支 远程新建了一个分支 xff0c 但是本地并没有这个分支
  • python 分割字符串,只分割一次

    需求背景 在开发过程中 xff0c 需要对部分字符串进行切割 xff0c 但是这个字符串是用户输入的 xff0c 用户可能会输入下划线 xff0c 如果只是单纯的分割 xff0c 则分割的结果不对 xff0c 需要对这个进行处理 解决方案
  • mysql查询其中一个字段 和 查询所有字段效率比较

    第一种 查询所有 xff0c 10000次 xff0c span class token keyword sql span span class token operator 61 span span class token string
  • tr td设置内边距 和 外边距

    tr tr xff1a 设置 margin 和 padding 都无效 td td xff1a 设置 margin无效 设置 padding有效
  • apppium 两个H5页面之间进行切换pagesource打印出的是上个页面的信息

    背景 当前项目有很多个H5界面 xff0c 在进行上下文切换的时候 xff0c 发现打印的pagesource是上一个H5页面的元素 原因 H5页面需要 chromedrive exe进行加载 xff0c 需要杀掉上一个页面的 chrome
  • uiautomatorviewer手机横屏显示截图调整为竖屏

    背景 手机app部分界面是横屏显示 xff0c 但是 uiautomatorviewer是竖屏显示 解决方案 将竖屏的图片 保存下来 xff0c 然后将图片旋转为横屏 再次打开 解决 1 点击保存按钮 xff0c 保存这个图片 2 将图片调
  • 版本管理-创建git仓库

    创建git仓库 把已有的项目代码纳入git管理 span class token builtin class name cd span 项目代码所在文件夹 span class token function git span init 新建
  • git 撤销commit

    撤销未push的commit span class token comment 用户已经执行的操作 span span class token function git span span class token function add
  • Django整理01:启动流程

    目录 启动 启动 span class token comment 启动命令 xff1a span python manage py runserver span class token comment 运行先文件的handler函数 sp
  • 差量更新问题记录

    问题 xff1a 升级后台配置了差量更新 xff0c 但是用户设备检测到的是全量更新 xff0c 测试设备检测到的是差量更新 原因 xff1a 差量更新需要具备的条件 xff1a 1 升级后台配置了差量更新的链接 2 设备对应的目录下有ba

随机推荐

  • Linux操作系统的启动过程

    Linux操作系统的启动过程 一 Linux操作系统的开机过程二 初始化进程服务三 服务管理命令 一 Linux操作系统的开机过程 Linux操作系统的开机过程可简记为 xff1a 两次检测 xff0c 一次装载 即首先对BIOS做初始化
  • manifest.json参数详解

    从官网文档翻译而来 xff0c 比大多数网上现有资源详细很多 xff0c 部分官网没有的属性通过stackoverflow xff0c 甚至是chromium源码查询而来 还有一些没注释的是查询不到或者本人无法确定的 官方文档地址 xff1
  • C语言经典例25-阶乘累加求和

    目录 1 题目2 分析3 实现4 运行结果 1 题目 求1 43 2 43 3 43 43 20 的和 2 分析 本题的本质就是求阶乘 xff0c 观察规律可以发现 xff0c 1 1 1 和
  • centos7 双击程序启动不了

    1 在终端输入ldd test 查看程序依赖的库 2 如果依赖库都存在 xff0c 双击程序启动不了 xff0c 但是在终端输入 test 却可以启动 原因解释 xff1a 在终端输入的程序是带路径的 xff0c 双击的时候是不带路径的 x
  • Ubuntu修改密码及密码复杂度策略设置方法

    版本查看 cat span class token operator span etc span class token operator span issue cat span class token operator span proc
  • 2022小米红米手机最新最全MIUI刷机教程内测版到稳定版 不清除数据(线刷、卡刷)

    文章目录 方法1 xff1a 解锁 线刷手机解锁解锁软件接入电脑刷机工具下载下载刷机包线刷 方法2 xff1a 小米助手卡刷包下载小米助手PC客户端打开手机USB调试模式连接小米助手卡刷miui卡刷包下载 起因是因为意外升级了一版内测版mi
  • TreeSet录入重复的元素及保证录入&输出顺序一致的Java实现

    Java萌新在学习路上遇到的一个扯dan的问题解法 知识点 Set TreeSet TreeSet自然排序 TreeSet比较器排序 Comparator 原题目 请编写main 方法 xff0c 按以下要求顺序 循环接收控制台录入的字符串
  • SpringBoot无法访问static文件夹 404问题

    使用spring boot 配置好后端 导入前端页面到resources 61 gt static 文件夹后 无法访问 但此时进入调试模式 访问controller的路径时 发现后台已经传送出去json数据 64 RequestMappin
  • Ubuntu虚拟机反复在登录界面循环问题

    登录Ubuntu的时候发现登录界面不对劲 xff0c 之前从来没有看到过 而且无法登录 xff0c 反复在登录界面循环 百度 xff0c 说原因有两个 xff1a 1 环境变量修改有问题 xff1b 2 显卡驱动有问题 xff1b 均尝试数
  • pycharm设置笔记

    目录 区分级别显示高亮日志 区分级别显示高亮日志 效果 设置log highlighting里填入 s E RROR s 即可 s E RROR s
  • Ubuntu设置开机自启动

    文章目录 前言一 基本概念二 操作步骤1 终端输入2 设置路径 总结 前言 本文介绍如何在Ubuntu设置开机自启动 一 基本概念 除了系统上配置的默认启动应用程序之外 xff0c gnome session properties 程序使用
  • uniapp 发布网站遇到的问题(跨域,nginx代理失败,index无法打开,手机端无法访问等)

    跨域 如果开发的应用直接是作为手机APP是不存在跨域问题的 xff0c 但是如果是网站形式就要考虑这个问题了 分为两点 xff1a 1 调试时 可通过设置maintest 2 发布后 可通过Nginx配置文件设置代理 nginx代理失败 1
  • 怎么在linux上安装vnc

    1 首先检查是否安装了VNC服务 输入命令 xff1a rpm qa grep vnc 2 安装VNC xff0c 首次执行vncserver需要设置密码 xff0c 可以创建多个桌面 xff0c 执行多次vncserver命令即可 roo
  • VNC修改端口号

    1 vnc的默认端口是自己配置的 xff0c 想要修改vncserver的配置 xff0c 需要先找配置文件路径 root 64 node04 which vncserver usr bin vncserver 2 通过查找以前配置的端口
  • onNewIntent使用遇到的坑

    onCreate是用来创建一个Activity也就是创建一个窗体 xff0c 但一个Activty处于任务栈的顶端 xff0c 若再次调用startActivity去创建它 xff0c 则不会再次创建 若你想利用已有的Acivity去处理别
  • CentOS7使用firewall-cmd打开关闭防火墙与端口

    一 centos7版本对防火墙进行加强 不再使用原来的iptables 启用firewalld 1 firewalld的基本使用 启动 xff1a systemctl start firewalld 查状态 xff1a systemctl
  • 算法数学基础-排列组合(题目取自牛客网)

    基础理论 xff1a 排列 有限集的子集按某种条件的序化法排成列 排成一圈 不许重复或许重复等 从n个不同元素中每次取出m xff08 1 m n xff09 个不同元素 xff0c 排成一列 xff0c 称为从n个元素中取出m个元素的无重
  • 关于对Spring框架的详解

    Spring框架 基本概念Spring的形成主要模块三层架构Spring的优点对于Spring 框架中都用到设计模式 xff1a 基本概念 Spring框架是由于软件开发的复杂性而创建的 Spring使用的是基本的JavaBean来完成以前
  • vs2015 提示严重性代码说明项目文件行禁止显示状态 错误C4996 'scanf': This function or variable may be unsafe.

    在 vs2015 中使用scanf时总是提示 unsafe 报出错误 xff0c 解决办法是在已经建立的项目中 xff0c 以后可能需要经常进行再不同的项目进行这项操作 xff1a 项目 gt 属性 gt c c 43 43 gt 常规 g
  • base7. ThreadPool线程池类——生产者与消费者模型

    ThreadPool类图 数据成员 xff1a MutexLock mutex xff1a 一个MutexLock类型的互斥变量mutex Condition cond xff1a 一个Condition类型的条件变量cond string