【Linux 23】线程池

文章目录

  • 🌈 一、线程池的概念
  • 🌈 二、线程池的应用场景
  • 🌈 三、线程池的实现

🌈 一、线程池的概念

  • 线程池 (thread pool) 是一种利用池化技术的线程使用模式

  • 虽然创建线程的代价比创建进程的要小很多,但小并不意味着没有。如果每次处理任务都要创建线程,积少成多下,代价还是蛮高的。

  • 而线程池就可以解决这种问题,提前先创建出一批线程,没任务时,让这些线程泡在池子里睡觉,来任务后,将这些线程从池子里叫起来干活。

    • 水池里流淌的是水流,而线程池里流淌的则是执行流 (线程)。
  • 不要被线程池这个称呼给套住了,本质上来说,线程池 = 任务队列 + 条件变量 + 多执行流

    • 当任务队列中没任务时,让一堆线程在指定条件变量下等待;
    • 当任务队列中有任务时,会唤醒在条件变量下等待的线程,让被唤醒的线程从任务队列中获取任务。
  • 说到底,线程池本质上就是个生产消费模型

image-20240923163036559

🌈 二、线程池的应用场景

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。
    • 例如 web 服务器完成网页请求,这种单个任务小,但任务量大的任务,就很适合使用线程池技术。
  2. 对性能要求苛刻的应用,要求服务器迅速响应客户请求。
  3. 接收突发性的大量请求,但不至于使服务器因此产生大量线程的应用。
    • 在没有线程池的情况下,如果没有线程池,短时间内将产生大量线程,可能使内存到达极限。

🌈 三、线程池的实现

  • 当前要实现一个主线程不停的往任务队列中放任务,然后让线程池中的线程从任务队列中获取任务,再进行任务处理的一个简易线程池。

  • 实现的这个简易的线程池整体分为线程池部分代码、任务类型部分代码、主线程部分代码这三部分。

  • 这三部分代码可以分别写在三个文件中 (记得包含对应头文件),也可以放在一个文件中,此处为了方便演示就全写在一个文件中。

#include <queue>
#include <iostream>
#include <unistd.h>
#include <pthread.h>using std::cerr;
using std::cout;
using std::endl;
using std::queue;/* ---------- 任务类型代码设计 ---------- */
class task
{
private:int _x;   // 左操作数int _y;   // 右操作数char _op; // 操作符public:task(int x = 0, int y = 0, char op = 0): _x(x), _y(y), _op(op){}// 处理任务的方法void run(){int result = 0; // 记录计算结果switch (_op){case '+':result = _x + _y;break;case '-':result = _x - _y;break;case '*':result = _x * _y;break;case '/':if (_y == 0){cerr << "除零错误" << std::endl;return;}else{result = _x / _y;}break;case '%':if (_y == 0){std::cerr << "模零错误" << std::endl;return;}else{result = _x % _y;}break;default:cerr << "非法运算符" << endl;return;}cout << "新线程 [" << pthread_self() << "] 获取任务成功, 任务的处理结果为: "<< _x << " " << _op << " " << _y << " = " << result << endl;}~task(){}
};/* ---------- 线程池代码设计 ---------- */
#define NUM 5               // 任务队列的容量template <typename T>
class thread_pool
{
private:queue<T> _task_queue;   // 任务队列int _thread_num;        // 线程池中线程的数量pthread_mutex_t _mutex; // 线程池中的线程的互斥锁pthread_cond_t _cond;   // 线程池中的线程的条件变量private:// 判断任务队列是否为空bool is_empty(){return _task_queue.size() == 0;}// 上锁void lock_queue(){pthread_mutex_lock(&_mutex);}// 解锁void unlock_queue(){pthread_mutex_unlock(&_mutex);}// 让线程去指定条件变量处等待等待void wait(){pthread_cond_wait(&_cond, &_mutex);}// 唤醒在指定条件变量处等待的线程void wakeup(){pthread_cond_signal(&_cond);}public:// 线程池的构造函数thread_pool(int num = NUM): _thread_num(num){pthread_mutex_init(&_mutex, nullptr); // 初始化互斥锁pthread_cond_init(&_cond, nullptr);   // 初始化条件变量}// 线程池中的线程所要执行的函数static void *routine(void *arg){pthread_detach(pthread_self());thread_pool *self = (thread_pool *)arg;// 不断从任务队列获取中任务,然后处理这些任务while (true){self->lock_queue();     	// 获取任务前, 先对任务队列上锁while (self->is_empty())	// 如果任务队列为空, 则让线程去休眠self->wait();T task;               		// 定义任务对象self->pop(&task);     		// 用定义好的任务对象从任务队列中获取任务self->unlock_queue(); 		// 获取任务后, 要对任务队列解锁task.run();           		// 处理获取到的任务}}// 初始化线程池 (为线程池创建一批线程)void thread_pool_init(){pthread_t tid;for (int i = 0; i < _thread_num; i++)pthread_create(&tid, nullptr, routine, this); // 传入 this 指针作为 routine 函数的参数}// 往任务队列放任务(主线程调用)void push(const T &task){lock_queue();               // 给任务队列上锁_task_queue.push(task);     // 往任务队列中放入任务unlock_queue();             // 为任务队列解锁wakeup();                   // 来活了, 唤醒在线程池中休眠的线程}// 从任务队列获取任务(线程池中的线程调用)void pop(T *task){*task = _task_queue.front();_task_queue.pop();}// 线程池的析构函数~thread_pool(){pthread_mutex_destroy(&_mutex); // 销毁互斥锁pthread_cond_destroy(&_cond);   // 销毁条件变量}
};/* ---------- 主线程代码设计 ---------- */
int main()
{srand((unsigned int)time(nullptr)); // 随机数种子thread_pool<task> *tp = new thread_pool<task>; // 定义线程池对象tp->thread_pool_init();                        // 初始化线程池当中的线程const char *op = "+-*/%";                      // 操作符集// 不断往任务队列塞计算任务while (true)                        {sleep(1);int x = rand() % 100;           // 左操作数int y = rand() % 100;           // 右操作数int index = rand() % 5;         // 随机获取操作符集中的某个操作符的下标task task(x, y, op[index]);     // 构造一个任务对象tp->push(task);                 // 将构造的任务对象放入任务队列cout << "主线程放入任务完毕, 放入的任务为: "<< x << " " << op[index] << " " << y << " = ?" << endl;}return 0;
}

  • 因为没有将屏幕这个临界资源也用锁保护起来,因此才会有一开始的主线程和新线程打印的内容混在一起的状况出现。
  • 要解决这个问题,可以直接使用互斥锁将访问屏幕这个临界资源的临界区保护起来就行。

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

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

相关文章

一篇文章快速学会docker容器技术

目录 一、Docker简介及部署方法 1.1Docker简介 1.1.1什么是docker 1.1.2 docker在企业中的应用场景 1.1.3 docker与虚拟化的对比 1.1.4 docker的优势 二 、部署docker 2.1 容器工作方法 2.2 部署第一个容器 2.2.1 配置软件仓库 2.2.2 安装docker-ce并启动服务 2.2.…

【AIGC】ChatGPT提示词解析:如何生成爆款标题、节日热点文案与完美文字排版

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;情绪化的吸睛爆款标题提示词使用方法 &#x1f4af;紧跟节日热点选题文案提示词使用方法 &#x1f4af;高效文字排版技巧提示词使用方法 &#x1f4af;小结 &#x1f4af…

数据结构-链表笔记

移除节点 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListN…

Oracle数据库体系结构基础

关于Oracle体系结构 基于Oracle11g体系结构 目标&#xff1a; 了解Oracle体系结构掌握逻辑存储结构掌握物理存储结构熟悉Oracle服务器结构熟悉常用的数据字典 Oracle数据库管理中的重要的三个概念 实例&#xff08;instance):实例是指一组Oracle后台进程以及在服务器中分配…

安宝特分享 | AR技术重塑工业:数字孪生与沉浸式培训的创新应用

在数字化转型的浪潮中&#xff0c;AR&#xff08;增强现实&#xff09;技术与工业的结合正在呈现新的趋势和应用延伸。特别是“数字孪生”概念的崛起&#xff0c;为AR技术在工业中提供了独特而创新的切入点。 本文将探索AR如何与数字孪生、沉浸式体验和实用案例相结合&#xf…

ResNet50V2:口腔癌分类

本文为为&#x1f517;365天深度学习训练营内部文章 原作者&#xff1a;K同学啊 一 ResNet和ResNetV2对比 改进点&#xff1a;(a)original表示原始的ResNet的残差结构&#xff0c;(b)proposed表示新的ResNet的残差结构&#xff0c;主要差别就是(a)结构先卷积后进行BN和激活函数…

JAVAEE如何实现网页(jsp)间的数据传输?一文总结

刚刚接触到JAVAEE的WEB开发&#xff0c;解释不周的地方希望感谢指正&#xff01;&#xff01;&#xff01; 情景如下&#xff1a; 我的使用是21版的IDEA&#xff0c;9.03版本的tomcat&#xff0c;来做一个示范。 构建项目 点击下一步 -> 完成&#xff0c;等待项目构建结束…

袋鼠云数据资产平台:数据模型标准化建表重构升级

数据模型是什么&#xff1f;简单来说&#xff0c;数据模型是用来组织和管理数据的一种方式。它为构建高效且可靠的信息系统提供了基础&#xff0c;不仅决定了如何存储和管理数据&#xff0c;还直接影响系统的性能和可扩展性。 想要建立一个良好的数据模型&#xff0c;设计时需…

Ubuntu开机进入紧急模式处理

文章目录 Ubuntu开机进入紧急模式处理一、问题描述二、解决办法参考 Ubuntu开机进入紧急模式处理 一、问题描述 Ubuntu开机不能够正常启动&#xff0c;自动进入紧急模式&#xff08;You are in emergency mode&#xff09;。具体如下所示&#xff1a; 二、解决办法 按CtrlD进…

在 Kali Linux 中安装 Impacket

步骤 1&#xff1a;更新系统 打开终端并确保你的系统是最新的&#xff1a; sudo apt update && sudo apt upgrade -y 步骤 2&#xff1a;安装依赖 在安装 Impacket 之前&#xff0c;你需要确保安装了 Python 和一些必要的依赖。通常&#xff0c;Kali 已经预装了 Pytho…

基于R语言机器学习遥感数据处理与模型空间预测

随机森林作为一种集成学习方法&#xff0c;在处理复杂数据分析任务中特别是遥感数据分析中表现出色。通过构建大量的决策树并引入随机性&#xff0c;随机森林在降低模型方差和过拟合风险方面具有显著优势。在训练过程中&#xff0c;使用Bootstrap抽样生成不同的训练集&#xff…

C++ set,multiset与map,multimap的基本使用

1. 序列式容器和关联式容器 string、vector、list、deque、array、forward_list等STL容器统称为序列式容器&#xff0c;因为逻辑结构为线性序列的数据结构&#xff0c;两个位置存储的值之间一般没有紧密的关联关系&#xff0c;比如交换一下&#xff0c;他依旧是序列式容器。顺…

reverse--->恶意代码分析(第一次接触)。

学习笔记。 前言&#xff1a;第一次接触&#xff0c;朋友发给我的。 取自&#xff1a;22年信息安全管理与评估二阶段。 要求&#xff1a; 下载 查壳 32ida打开。 先上微步云沙箱看看&#xff1a; 样本报告-微步在线云沙箱 (threatbook.com)https://s.threatbook.com/repor…

css 中 ~ 符号、text-indent、ellipsis、ellipsis-2、text-overflow: ellipsis、::before的使用

1、~的使用直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:…

Python批量处理客户明细表格数据,挖掘更大价值

批量处理 .xls 数据并进行归类分析以挖掘内在价值&#xff0c;通常涉及以下步骤&#xff1a; 读取数据&#xff1a;使用 pandas 库读取 .xls 文件。数据清洗&#xff1a;处理缺失值、异常值、重复值等。数据转换&#xff1a;对数据进行必要的转换&#xff0c;如日期格式统一、…

C嘎嘎入门篇:类和对象(2)

前言&#xff1a; 上一篇小编讲了类和对象&#xff08;1&#xff09;&#xff0c;当然&#xff0c;在看这篇文章之前&#xff0c;读者朋友们一定要掌握好前面的基础内容&#xff0c;因为这篇和前面息息相关&#xff0c;废话不多说&#xff0c;下面小编就加快步伐&#xff0c;开…

【JavaEE】http/https 超级详解

&#x1f525;个人主页&#xff1a; 中草药 &#x1f525;专栏&#xff1a;【Java】登神长阶 史诗般的Java成神之路 &#x1f98a;一.定义 HTTP&#xff08;HyperText Transfer Protocol&#xff09;即超文本传输协议&#xff0c;他是应用非常广泛的应用层协议&#xff0c;是…

【CSS in Depth 2 精译_041】6.4 CSS 中的堆叠上下文与 z-index(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09;第二章 相对单位&#xff08;已完结&#xff09;第三章 文档流与盒模型&#xff08;已完结&#xff09;第四章 Flexbox 布局&#xff08;已…

TryHackMe 第5天 | Pre Security (四)

该学习路径讲解了网络安全入门的必备技术知识&#xff0c;比如计算机网络、网络协议、Linux命令、Windows设置等内容。过去三篇已经对前三块内容进行了简单介绍&#xff0c;本篇博客将记录 Windows设置 部分。 Windows Fundamentals Part 1 对于 Windows &#xff0c;肯定会感…

(最新已验证)stm32 + 新版 onenet +dht11+esp8266/01s + mqtt物联网(含微信小程序)上报温湿度和控制单片机(保姆级教程)

物联网实践教程&#xff1a;微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——汇总 前言 之前在学校获得了一个新玩意&#xff1a;ESP-01sWIFI模块&#xff0c;去搜了一下这个小东西很有玩点&#xff0c;远程控制LED啥的&#xff0c;然后我就想…