【linux多线程(四)】——线程池的详细解析(含代码)

2023-11-15

目录

什么是线程池?

线程池的应用场景 

线程池的实现

线程池的代码(C++) 
 


【linux线程(壹)】——初识线程(区分线程和进程,线程创建的基本操作)
【线程(二)】——互斥量的详细解析
【线程(三)】———条件变量的详细解析

什么是线程池?

线程池是一种线程使用模式,它是将一定数量线程和缓冲队列预存在一个池子中,池子中的线程轮流的往任务队列中拿去任务并完成任务,而任务队列往外开发一个接口,使其他线程能够往任务队列中推送任务。

线程池的优点:

线程池能够减少线程的创建和销毁所消耗的时间和系统资源的开销,如果不使用线程池,将可能造成系统创建大量的同类线程而导致消耗完内存或“过度切换”的问题。

线程池的应用场景 

1,需要大量线程来完成任务,且完成任务的时间较短,WEB服务器完成网页请求这样的任务使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,但对于长时间的任务,比如一个Telnet连接请求,线程池的优点不明显,因为Telnet会话时间比线程的创建时间太多了。

2.对性能苛刻要求的的应用,比如服务器迅速响应客户请求。

3.接受突发的大量请求时,但不至于使服务器创建大量的线程,在没有线程池情况下,将产生大量的线程,短时间内会产生大量的线程可能使内存达到极限,出现错误。

线程池的实现

线程池的成员变量:

  • 任务队列,quueu<T> q;
  • 线程个数,int num;
  • 互斥量,pthread_mutex_t lock;
  • 条件变量,pthread_cond_t cond;

创建线程池,需要创建一个任务队列和一定数量的线程。由于每次只能有一个线程进入队列中放任务和拿任务,所以此时需要定义一个互斥量进行维护,如果任务队列中的没有任务,此时线程就不能进入任务队列中,所以就创建一个条件变量。


 

线程池的代码(C++) 

 makefile文件

threadpool:threadpool.cc    
  g++ $^ -o $@ -lpthread                                                                                                                                     
    
clean:    
  rm -f threadpool

Task.hpp文件

#pragma  once    
#include<iostream>    
#include<stdio.h>    
using namespace std;    
class Task    
{    
  private:    
    int x;int y;    
    char op;                                                                                                                                                 
  public:       
    Task(int _x,int _y,char _op)    
      :x(_x)                        
      ,y(_y)    
      ,op(_op){ }    
    Task()           
    {};       
    void Run()    
    {             
      int ret=0;    
      switch(op){    
        case '+':    
          ret=x+y;    
          break;                     
        case '-':                    
          ret=x-y;                   
          break;                     
        case '*':            
          ret=x*y;
          break;
          case '/':
          ret=x/y;
          break;
          case '%':
          ret=x%y;
          break;
      }
      printf("%d %c %d = %d\n",x,op,y,ret);
    } 
};                                    

 threadpool.hpp文件 

#pragma once    
#include<iostream>                                                                                                                                           
#include<queue>    
#include<pthread.h>    
#include<unistd.h>    
using namespace std;    
    
    
#define NUM 4    
template<class T>    
class ThreadPool    
{    
  private:    
    queue<T> q;//任务队列    
    int thread_num;//线程池的线程数量    
    pthread_mutex_t lock;//互斥锁    
    pthread_cond_t cond;//条件变量    
  public:    
    ThreadPool(int num=NUM)//初始化变量
      :thread_num(num){    
        pthread_mutex_init(&lock,NULL);    
        pthread_cond_init(&cond,NULL);    
    }    
    
    bool Empty()    
    {    
      return q.size()==0?true:false;     
    }    
    
   static  void* Routine(void* arg)//线程执行流    
    {    
      pthread_detach(pthread_self());//线程分离    
      ThreadPool* self=(ThreadPool*)arg;
      while(1)
      {
        self->LockQueue();
        while(self->Empty())//任务队列是否为空
        {
          self->Wait();
        }
        T data;
        self->Pop(data);//取出任务
        self->UnlockQueue();

        cout<<pthread_self()<<"# ";                                                                                                                          
        //处理任务
        data.Run();//处理任务
        sleep(1);
      }
    }

    void Wait()//线程等待
    {
      pthread_cond_wait(&cond,&lock);
    }

    void LockQueue()//锁住队列
    {
      pthread_mutex_lock(&lock);
    }

    void UnlockQueue()//解锁队列
    {
      pthread_mutex_unlock(&lock);
    }

    void ThreadPoolInit()
    {
      pthread_t tid;
      for(int i=0;i<thread_num;i++)//创建线程池中的线程
      {
        pthread_create(&tid,NULL,Routine,(void*)this);
      }
    }

    void Push(const T& in)//将任务推进任务队列中
    {
      LockQueue();
      q.push(in);
      UnlockQueue();
      SignalThread();
    }

    void SignalThread()//唤醒cond变量下的线程
    {
      pthread_cond_signal(&cond);
    }

    void Pop( T& out)//取出任务队列中的任务
    {
      out=q.front();
      q.pop();
    }

    ~ThreadPool()
    {
      pthread_mutex_destroy(&lock);
      pthread_cond_destroy(&cond);
    }
};                      

threadpool.cc 文件

#include"threadpool.hpp"    
#include"Task.hpp"    
#include<time.h>    
#include<stdlib.h>    
int main()    
{    
  ThreadPool<Task> * q=new ThreadPool<Task>();//创建线程池    
  q->ThreadPoolInit();    
  srand((long int)time(NULL));    
  while(1)  //主线程往任务队列中放任务  
  {    
    char arr[]="+-*/%";    
    int x=rand()%100+1;    
    int y=rand()%100+1;    
    char op=arr[rand()%5];    
    Task t(x,y,op);//创建任务    
    q->Push(t);//将任务推送给队列中    
  }                                                                                                                                                          
  return 0;    
}  

运行结果:

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

【linux多线程(四)】——线程池的详细解析(含代码) 的相关文章

  • xsel -o 对于 OS X 等效项

    是否有一个等效的解决方案可以在 OS X 中抓取选定的文本 就像适用于 Linux 的 xsel o 一样 只需要当前的选择 这样我就可以在 shell 脚本中使用文本 干杯 埃里克 你也许可以安装xsel在 MacOS 上 更新 根据 A
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • bluetoothctl 到 hcitool 等效命令

    在 Linux 中 我曾经使用 hidd connect mmac 来连接 BT 设备 但自 Bluez5 以来 这种情况已经消失了 我可以使用 bluetoothctl 手动建立连接 但我需要从我的应用程序使用这些命令 并且使用 blue
  • Android:ANT 构建失败,并显示 google-play-services-lib:“解析为没有项目的 project.properties 文件的路径”

    我正在尝试使用 ANT 构建我的应用程序 但在包含 google play services lib 库项目后 我惨遭失败 Step 1 我在 project properties 文件中设置了对库项目的引用 android library
  • 应用程序无缘无故地被杀死。怀疑 BSS 高。如何调试呢?

    我已经在CentOs6 6中成功运行我的应用程序 最近 硬件 主板和内存 更新了 我的应用程序现在毫无理由地被杀死 root localhost PktBlaster PktBlaster Killed 文件和 ldd 输出 root lo
  • Jenkins中找不到环境变量

    我想在詹金斯中设置很多变量 我试过把它们放进去 bashrc bash profile and profile of the jenkins用户 但 Jenkins 在构建发生时找不到它们 唯一有效的方法是将所有环境变量放入Jenkinsf
  • Linux中的CONFIG_OF是什么?

    我看到它在很多地方被广泛使用 但不明白在什么场景下我需要使用它 What is 配置 OF OF 的全名是什么 打开固件 这是很久以前发明的 当时苹果公司正在生产基于 PowerPC CPU 的笔记本电脑 而 Sun Microsystem
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • sendfile64 只复制约2GB

    我需要使用 sendfile64 复制大约 16GB 的文件 到目前为止我所取得的成就是 include
  • Linux 中的动态环境变量?

    Linux 中是否可以通过某种方式拥有动态环境变量 我有一个网络服务器 网站遵循以下布局 site qa production 我想要一个环境变量 例如 APPLICATION ENV 当我在 qa 目录中时设置为 qa 当我在生产目录中时
  • 加载数据infile,Windows和Linux的区别

    我有一个需要导入到 MySQL 表的文件 这是我的命令 LOAD DATA LOCAL INFILE C test csv INTO TABLE logs fields terminated by LINES terminated BY n
  • 所有平台上的java

    如果您想用 java 为 Windows Mac 和 Linux 编写桌面应用程序 那么所有这些代码都相同吗 您只需更改 GUI 即可使 Windows 应用程序更像 Windows 等等 如果不深入细节 它是如何工作的 Java 的卖点之
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • 如何在Linux内核源代码中打印IP地址或MAC地址

    我必须通过修改 Linux 内核源代码来稍微改变 TCP 拥塞控制算法 但为了检查结果是否正确 我需要记录 MAC 或 IP 地址信息 我使用 PRINTK 函数来打印内核消息 但我感觉很难打印出主机的MAC IP地址 printk pM
  • PHP 从命令行启动 gui 程序,但 apache 不启动

    首先 我阅读了有类似问题的人的一些帖子 但所有答案都没有超出导出 DISPLAY 0 0 和 xauth cookies 这是我的问题 提前感谢您的宝贵时间 我开发了一个小库 它使用 OpenGL 和 GLSL 渲染货架 过去几天我将它包装
  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • iptables通过注释删除特定规则

    我需要删除一些具有相同评论的规则 例如 我有带有 comment test it 的规则 所以我可以像这样获得它们的列表 sudo iptables t nat L grep test it 但是我怎样才能删除所有带有注释 测试它 的 PR
  • jpegtran 优化而不更改文件名

    我需要优化一些图像 但不更改它们的名称 jpegtran copy none optimize image jpg gt image jpg 但是 这似乎创建了 0 的文件大小 当我对不同的文件名执行此操作时 大小仍然完全相同 怎么样 jp
  • Linux 中什么处理 ping?

    我想覆盖 更改 linux 处理 ping icmp echo 请求数据包的方式 这意味着我想运行自己的服务器来回复传入的 icmp 回显请求或其他 数据包 但为了使其正常工作 我想我需要禁用 Linux 的默认 ping icmp 数据包
  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少

随机推荐

  • python实现电影院仿真(SimPy)

    SimPy Simulating Real World Processes With Python 仿真环境 电影院仿真 目标 减少顾客的平均等待时间 少于10分钟 在开始仿真前 先思考这个仿真过程 顾客在坐下来看电影前需要经过哪些步骤 到
  • Oracle 错误一览表.docx

    ORA 00001 违反唯一约束条件 ORA 00017 请求会话以设置跟踪事件 ORA 00018 超出最大会话数 ORA 00019 超出最大会话许可数 ORA 00020 超出最大进程数 ORA 00021 会话附属于其它某些进程 无
  • centos7下Mercurial (hg)3.9.2版的安装配置及在sts使用mercurial插件clone,pull,commit,push

    Mercurial 已经在centos7的安装源里存在 Mercurial是一种轻量级分布式版本控制系统 采用Python语言实现 易于学习和使用 扩展性强 其是基于GNU General Public License GPL 授权的开源项
  • matlab数据类型和转换

    转自 http hi baidu com xmf6227 blog item 97ca2ddf98f1b61f495403cb html Matlab中有15种基本数据类型 主要是整型 浮点 逻辑 字符 日期和时间 结构数组 单元格数组以及
  • Pytorch面试题整理(2023.09.10)

    1 pytorch如何微调fine tuning 在加载了预训练模型参数之后 需要finetuning 模型 可以使用不同方式finetune 局部微调 加载了模型参数后 只想调节最后几层 其他层不训练 也就是不进行梯度计算 pytorch
  • 10.1-迁移学习

    迁移学习指的就是 假设你手上有一些跟你现在要进行的task没有直接相关的data 那你能不能用这些没有直接相关的data来帮助我们做一些什么事情 比如说 你现在做的是猫跟狗的classifer 那所谓没有什么直接相关的data是什么意思呢
  • win10 wsl 安装 ubuntu 16.04

    背景 因为大多数是在单系统上开发 现在想装win10 ubuntu共存 但双系统切换好麻烦 于是有了在win10里利用wsl装子系统的想法 操作 启动wsl 因为微软商店没有ubuntu16 04 于是到官网下载ubuntu16 04 其他
  • 解决Vue引用Swiper4插件无法重写分页器样式问题

    最近在尝试用nuxtjs来搭建新的站点 但是平时在jquery里面用惯的一些插件一到vue上面引用就各种不顺畅 本文记录一下在用Swiper插件来做轮播图的时候遇到的问题 至于怎么在vue里面引用插件就不累赘了 npm能告诉你 Swiper
  • 一个小时内学习 SQLite 数据库

    SQLite 是一个开源的嵌入式关系数据库 实现自包容 零配置 支持事务的SQL数据库引擎 其特点是高度便携 使用方便 结构紧凑 高效 可靠 与其他数据库管理系统不同 SQLite 的安装和运行非常简单 在大多数情况下 只要确保SQLite
  • 好用的插件介绍-Clear Cache Chrome插件

    clear cache插件是一款用于清理谷歌浏览器的chrome清理缓存插件 该插件支持清理应用程序缓存 缓存 Cookie 下载 文件系统 表单数据 历史 索引数据库 本地存储 插件数据 密码和WebSQL 你只需要在安装了这款插件后在设
  • VSCode中Python代码自动提示

    自己写的模块 VSCode中无法自动提示 可以按下面步骤试试 1 添加模块路径 文件 设置 首选项 搜索autoComplete 点击 在settings json中编辑 添加模块路径 python autoComplete extraPa
  • nrm安装与配置

    1 nrm安装与配置 npm 介绍 nrm npm registry manager 是npm的镜像源管理工具 有时候国外资源太慢 使用这个就可以快速地在 npm 源间切换 参考文章 西北码农 安装 在命令行执行命令 npm install
  • html 邮件乱码怎么办,如何解决html邮件乱码问题

    html邮件乱码的解决办法 1 在mail函数前一行打印message内容 2 将邮件内容保存为html文件后查看 3 设置UTF 8编码 本文操作环境 windows7系统 HTML5版 Dell G3电脑 如何解决html邮件乱码问题
  • Jenkins 持续集成:Linux 系统 两台机器互相免密登录

    背景知识 我们把public key放在远程系统合适的位置 然后从本地开始进行ssh连接 此时 远程的sshd会产生一个随机数并用我们产生的public key进行加密后发给本地 本地会用private key进行解密并把这个随机数发回给远
  • day21

    530 二叉搜索树的最小绝对差 先转换为有序list 再比较差值 501 二叉搜索树中的众数 先转换为有序list 再进行众数统计寻找 236 二叉树的最近公共祖先 后序遍历 再根据返回的值寻找祖先 package algor traini
  • 3d打印,机器人,计算机,3D打印的机器人将教孩子计算机编码!

    原标题 3D打印的机器人将教孩子计算机编码 随着我们的世界变得日益数字化的 越来越多的编码和计算机编程工作如雨后春笋般冒出 需要越来越多的人在编码语言 成为精通 这种先进的计算机知识将更加为下一代更重要 因为2024年 超过100万以上的编
  • Linux 三分钟学会虚拟机与外网和主机互通

    首先准备好一台安装好的虚拟机 字符界面也一样 配置虚拟网卡 添加一张虚拟网卡用来连接主机和虚拟机 通过图中步骤设置好 最后和最后那张图显示一样 确定 右击需要配置网络的虚拟机 单击添加 选中网络适配器 然后单击确定 点击自定义 然后选择刚刚
  • C++ 多态虚函数表(VS2013)

    对于含有虚函数的类 基类或者自身 自身非纯虚函数 的对象 都拥有一个指向虚函数表的指针 占一个指针大小的内存 在类成员变量之前 相当于第一个成员变量 多重继承的时候 几个基类就几个指针 就几个虚函数表 每个类的虚函数表确定了各个方法指向那个
  • Hadoop3.0.3 HDFS 常用shell 命令

    1 启动Hadoop start all sh root elk server sbin start all sh Starting namenodes on elk server 上一次登录 日 11月 24 21 57 43 CST 2
  • 【linux多线程(四)】——线程池的详细解析(含代码)

    目录 什么是线程池 线程池的应用场景 线程池的实现 线程池的代码 C linux线程 壹 初识线程 区分线程和进程 线程创建的基本操作 线程 二 互斥量的详细解析 线程 三 条件变量的详细解析 什么是线程池 线程池是一种线程使用模式 它是将