Linux之线程池与单例模式

目录

线程池

线程池代码

单例模式

饿汉模式单例模式

懒汉模式单例模式


在前几期,我们已经学习了多线程的创建和控制,学习了多线程中的同步和互斥,学习了多线程中的条件变量和信号量,基于此我们实现了基于阻塞队列和基于环形队列的生产者和消费者模型。本期将在此基础上进一步拓展学习,学习线程池相关的内容。

线程池

在学习线程池之前,我们通过一个场景为大家引入。图示如下。

当我们用户在用户层使用malloc函数和new操作符进行内存空间的申请时,必须由操作系统在底层使用对应的系统调用接口进行内存的申请,具体步骤为,进程由用户态切换为内核态,然后在内核态通过对应的内存算法进行内存的申请。但不免有一种情况,用户频繁的申请大小为1MB的空间,操作系统在底层不断地使用内存算法申请小块空间,在这种情景下,频繁地使用内存置换算法申请小块空间的代价是非常大的,效率也非常的低。基于此我们事先会通过操作系统在底层通过内存算法申请一大块空间,这样用户在申请时,可以直接从操作系统事先申请好的空间中去申请,不用再让操作系统频繁地使用内存算法申请小块空间,大大提高了效率。所以,内存池也是类似的原理,最终为提高了代码的执行效率。 

内存池: 提前准备好的线程,用来随时处理任务,我们就称作线程池。

线程池代码

创建一个可以处理多个任务的线程池。

ThreadPool.hpp

#pragma once
#include <queue>
#include <pthread.h>
#include <iostream>using namespace std;namespace threadpool
{const int g_num = 5;template <class T>class ThreadPool{public:ThreadPool(const int &num = g_num) : _num(num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);}~ThreadPool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}void Wait(){pthread_cond_wait(&_cond, &_mutex);}void Lock(){pthread_mutex_lock(&_mutex);}void Unlock(){pthread_mutex_unlock(&_mutex);}void Pop(T *out){*out = _task_queue.front();_task_queue.pop();}void Push(const T &data){Lock();_task_queue.push(data);Unlock();Wakeup();}void Wakeup(){pthread_cond_signal(&_cond);}static void *Rountine(void *args){// 线程分离,分线程退出时不用主线程去等待。pthread_detach(pthread_self());ThreadPool<T> *tp = (ThreadPool<T> *)args;while (true){tp->Lock();// 分线程去处理任务while (tp->_task_queue.empty()){tp->Wait();}T t;tp->Pop(&t);tp->Unlock();std::cout<<pthread_self()  << "得到的数据为 " << t << std::endl;}}void InitThreadPool(){pthread_t tid;for (int i = 0; i < g_num; i++){pthread_create(&tid, nullptr, Rountine, (void *)this);}}private:// 存放任务的队列queue<T> _task_queue;// 表示线程池中线程的数目int _num;pthread_mutex_t _mutex;pthread_cond_t _cond;};}

test.cc

#include "ThreadPool.hpp"
#include <iostream>
#include <unistd.h>
#include <time.h>
using namespace std;
using namespace threadpool;int main()
{ThreadPool<int> tp;tp.InitThreadPool();// 随机数种子srand((long long)time(nullptr));while (true){int a=rand()%20;tp.Push(a);cout << "发送的数据为" << a << endl;sleep(1);}return 0;
}

运行结果如下。

由运行结果可知,运行结果符合预期。 

单例模式

在学习单例模式之前,我们了解一下什么是设计模式,模式其实就是特定的场景给予特定的解决方案。在人类社会中,成熟的行业都会有成熟的设计模式。何为单例模式,单例模式其实就是一个类只允许实例化出一个对象的设计模式。

饿汉模式单例模式

饿汉就是,工资日结。

懒汉模式单例模式代码。

template <class T>
class SigDistance
{
private:static SigDistance<T> _t;public:static SigDistance<T> *GetDistance(){return &_t;}
};

懒汉模式单例模式

 懒汉就是,工资月结。

template <class T>
class SigDistance
{
private:static SigDistance<T> *_t;
public:static SigDistance<T> *GetDistance(){if (_t == nullptr){_t=new SigDistance();}return _t;}
};SigDistance<T>* SigDistance<T>::_t = nullptr;

 基于懒汉单例模式的线程池

线程池往往只有一个,所以我们把线程池类设计成了单例模式,代码如下。

Thread.hpp

#pragma once
#include <queue>
#include <pthread.h>
#include <iostream>using namespace std;namespace threadpool
{const int g_num = 5;template <class T>class ThreadPool{private:ThreadPool<T>(const int &num = g_num) : _num(num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);}~ThreadPool<T>(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}ThreadPool<T>(const ThreadPool<T> &tp) = delete;ThreadPool<T> &operator=(const ThreadPool<T> &tp) = delete;void Wait(){pthread_cond_wait(&_cond, &_mutex);}void Lock(){pthread_mutex_lock(&_mutex);}void Unlock(){pthread_mutex_unlock(&_mutex);}public:void Pop(T *out){*out = _task_queue.front();_task_queue.pop();}void Push(const T &data){Lock();_task_queue.push(data);Unlock();Wakeup();}void Wakeup(){pthread_cond_signal(&_cond);}static ThreadPool<T> *GetDistance(){static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;if(_tp==nullptr){pthread_mutex_lock(&lock);if (_tp == nullptr){_tp = new ThreadPool<T>();}}_tp->InitThreadPool();pthread_mutex_unlock(&lock);return _tp;}static void *Rountine(void *args){// 线程分离,分线程退出时不用主线程去等待。pthread_detach(pthread_self());ThreadPool<T> *tp = (ThreadPool<T> *)args;while (true){tp->Lock();// 分线程去处理任务while (tp->_task_queue.empty()){tp->Wait();}T t;tp->Pop(&t);tp->Unlock();std::cout << pthread_self() << "得到的数据为 " << t << std::endl;}}void InitThreadPool(){pthread_t tid;for (int i = 0; i < g_num; i++){pthread_create(&tid, nullptr, Rountine, (void *)this);}}private:// 存放任务的队列queue<T> _task_queue;// 表示线程池中线程的数目int _num;static ThreadPool<T> *_tp;pthread_mutex_t _mutex;pthread_cond_t _cond;};template <class T>ThreadPool<T> *ThreadPool<T>::_tp = nullptr;
}

需要注意的是,静态成员变量需要再类外进行初始化。 

test.cc

#include "ThreadPool.hpp"
#include <iostream>
#include <unistd.h>
#include <time.h>
using namespace std;
using namespace threadpool;int main()
{ThreadPool<int> *tp = ThreadPool<int>::GetDistance();// 随机数种子srand((long long)time(nullptr));while (true){int a = rand() % 20;tp->Push(a);cout << "发送的数据为" << a << endl;sleep(1);}return 0;
}

运行结果如下。

运行结果符合预期。

以上便是线程池以及单例模式的所有内容。

本期内容到此结束^_^ 

 

 

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

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

相关文章

青蛙云的云服务器有哪些显著优势?

青蛙云的云服务器具有以下显著优势&#xff0c;这些特点使得它成为企业构建高效IT基础设施的重要选择&#xff1a; 1.高性能硬件 青蛙云服务器采用高性能的服务器硬件进行部署&#xff0c;确保服务的稳定性和高效运行&#xff0c;为用户提供卓越的计算能力。 2. 弹性资源 支持资…

赛车微型配件订销管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 赛车微型配件行业通常具有产品多样性、需求不确定性、市场竞争激烈等特点。配件供应商需要根据市场需求及时调整产品结构和库存&#xff0c;同时要把握好供应链管理和销售渠道。传统的赛车微型配件订销管理往往依赖于人工经验和简单的数据分析&#xff0c;效率低下且容易…

《上古重生》V20241127111039官方中文学习版

《上古重生》官方中文版https://pan.xunlei.com/s/VODab-jcgXUAgJbj2b1-11qUA1?pwdc7di# 一款考验玩家技巧的砍杀游戏&#xff0c;从玩家到敌人&#xff0c;通通身穿古代的厚重盔甲&#xff0c;进行“重量级”的近身搏斗。在充满Cult元素的第一人称视角大冒险中杀出一条血路吧…

什么是负载均衡?NGINX是如何实现负载均衡的?

大家好&#xff0c;我是锋哥。今天分享关于【什么是负载均衡&#xff1f;NGINX是如何实现负载均衡的&#xff1f;】面试题。希望对大家有帮助&#xff1b; 什么是负载均衡&#xff1f;NGINX是如何实现负载均衡的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源…

数组排序------冒泡排序

要求&#xff1a;给定一个数组&#xff0c;让数组升序&#xff08;降序&#xff09;排序 思路&#xff1a; 假设升序排序&#xff1a; ①&#xff1a;将数组中相邻元素从前往后依次进行比较&#xff0c;如果前一个元素比后一个元素大&#xf…

SpringBoot + 九天大模型(文生图接口)

目录 1、先到九天大模型的官网&#xff08;LLM Studio&#xff09;上订阅模型的推理服务&#xff0c;得到APIKey&#xff0c;后期需要使用它生成token才能调用模型的推理服务。 2、在SpringBoot项目里面的pom.xml文件中添加九天大模型的相关依赖&#xff0c;后面会使用到其中…

Leetcode 120. 三角形最小路径和 动态规划

原题链接&#xff1a;Leetcode 120. 三角形最小路径和 class Solution { public:int minimumTotal(vector<vector<int>>& triangle) {int n triangle.size();if (n 1)return triangle[0][0];int dp[n][n];dp[0][0] triangle[0][0];int res INT_MAX;for (in…

网络安全概论

网络安全概论--网络基础知识--防火墙技术--身份识别技术--虚拟专用网络--入侵检测技术--病毒和恶意代码 --业务连续性计划--安全管理--信息系统安全方案设计方法 一、网络安全面临的威胁 物理安全威胁、操作系统的安全缺陷、网络协议的安全缺陷、应用软件的实现缺陷、用户使…

设计模式 行为型 状态模式(State Pattern)与 常见技术框架应用 解析

状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为&#xff0c;使得对象看起来好像修改了它的类。这种设计模式的核心思想是将对象的状态和行为封装成不同的状态类&#xff0c;通过状态对象的行为改变来避免…

某团 mtgsig1.2 | sdkVersion: 3.0.0 签名算法分析记录(2025/1/9)

【作者主页】&#xff1a;小鱼神1024 【擅长领域】&#xff1a;JS逆向、小程序逆向、AST还原、验证码突防、Python开发、浏览器插件开发、React前端开发、NestJS后端开发等等 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#…

(二)最长公共子序列、最长上升子序列、最大子段和、三角形最小路径和、矩阵连乘、0-1背包

最近刚考完算法设计分析课的考试&#xff0c;复习总结一下期末考试的几道算法题吧 目录 LCR 095. 最长公共子序列 300. 最长递增子序列 53. 最大子数组和 LCR 100. 三角形最小路径和 矩阵连乘问题 0-1背包 LCR 095. 最长公共子序列 给定两个字符串 text1 和 text2&#xff…

聚类系列 (二)——HDBSCAN算法详解

在进行组会汇报的时候&#xff0c;为了引出本研究动机&#xff08;论文尚未发表&#xff0c;暂不介绍&#xff09;&#xff0c;需要对DBSCAN、OPTICS、和HDBSCAN算法等进行详细介绍。在查询相关资料的时候&#xff0c;发现网络上对于DBSCAN算法的介绍非常多与细致&#xff0c;但…

通义灵码在跨领域应用拓展之物联网篇

目录 一.引言 二.通义灵码简介 三.通义灵码在物联网领域的设备端应用 1.传感器数据采集 (1).不同类型传感器的数据读取 (2).数据转换与预处理 2.设备控制指令接收和执行 (1).指令解析与处理 (2).设备动作执行 四.通义灵码在物联网领域的云端平台应用 1.数据存储和管…

DolphinScheduler自身容错导致的服务器持续崩溃重大问题的排查与解决

01 问题复现 在DolphinScheduler中有如下一个Shell任务&#xff1a; current_timestamp() { date "%Y-%m-%d %H:%M:%S" }TIMESTAMP$(current_timestamp) echo $TIMESTAMP sleep 60 在DolphinScheduler将工作流执行策略设置为并行&#xff1a; 定时周期调度设置…

CISAW-ES应急服务方向信息安全事件分级

网络安全事件事件分级 网络安全事件分为四级&#xff1a;特别重大网络安全事件、重大网络安全事大网络安全事件、一般网络安全事件。 1&#xff0e;特别重大网络安全事件 符合下列情形之一的&#xff0c;为特别重大网络安全事件。 &#xff08;1&#xff09;重要网络和信息系…

油猴支持阿里云自动登陆插件

遇到的以下问题,都已在脚本中解决: 获取到的元素赋值在页面显示,但是底层的value并没有改写,导致请求就是获取不到数据元素的加载时机不定,尤其是弱网情况下,只靠延迟还是有可能获取不到,且登陆不丝滑,通过元素发现机制,解决此问题并做到丝滑登陆根据密钥计算校验码之…

B树与B+树:数据库索引的秘密武器

想象一下&#xff0c;你正在构建一个超级大的图书馆&#xff0c;里面摆满了各种各样的书籍。B树和B树就像是两种不同的图书分类和摆放方式&#xff0c;它们都能帮助你快速找到想要的书籍&#xff0c;但各有特点。 B树就像是一个传统的图书馆摆放方式&#xff1a; 1. 书籍摆放&…

城市生命线安全综合监管平台

【落地产品&#xff0c;有需要可留言联系&#xff0c;支持项目合作或源码合作】 一、建设背景 以关于城市安全的重要论述为建设纲要&#xff0c;聚焦城市安全重点领域&#xff0c;围绕燃气爆炸、城市内涝、地下管线交互风险、第三方施工破坏、供水爆管、桥梁坍塌、道路塌陷七…

成为LabVIEW自由开发者

成为LabVIEW自由开发者的体验可以非常丰富且具有挑战性&#xff0c;同时也充满了自我成长和多样化项目的机会。 ​ 1. 高度的灵活性与自由度 工作时间与地点&#xff1a;作为自由开发者&#xff0c;你可以自由选择工作时间和地点。你可以在家工作&#xff0c;也可以选择在咖啡…

用于与多个数据库聊天的智能 SQL 代理问答和 RAG 系统(3) —— 基于 LangChain 框架的文档检索与问答功能以及RAG Tool的使用

介绍基于 LangChain 框架的文档检索与问答功能&#xff0c;目标是通过查询存储的向量数据库&#xff08;VectorDB&#xff09;&#xff0c;为用户的问题检索相关内容&#xff0c;并生成自然语言的答案。以下是代码逻辑的详细解析&#xff1a; 代码结构与功能 初始化环境与加载…