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.rhkb.cn/news/505713.html

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

相关文章

The Dedicated Few (10 player)

The Dedicated Few (10 player) 少数精锐&#xff08;10人&#xff09; &#xff1a;以少于9人的阵容击败纳克萨玛斯的所有首领&#xff08;10人&#xff09; 历时2小时做完了&#xff0c;不容易啊&#xff0c;别人可以的咱也可以。 World of Warcraft [CLASSIC][80猎人][G…

List ---- 模拟实现LIST功能的发现

目录 listlist概念 list 中的迭代器list迭代器知识const迭代器写法list访问自定义类型 附录代码 list list概念 list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素…

vscode支持ssh远程开发

文章目录 一、生成ssh使用的公钥/密钥对二、使用vscode通过ssh连接服务器1.安装插件2.配置文件3.连接服务器4.新建文件夹&#xff0c;存放不同的任务 三、使用scp命令与服务器互传文件、文件夹1.检查Windows 系统是否支持scp命令2.在Windows系统本地的电脑向服务器传输文件、文…

Jmeter-压测时接口如何按照顺序执行

Jmeter-压测时接口如何按照顺序执行-临界部分控制器 在进行压力测试时&#xff0c;需要按照顺序进行压测&#xff0c;比如按照接口1、接口2、接口3、接口4 进行执行 查询结果是很混乱的&#xff0c;如果请求次数少&#xff0c;可能会按照顺序执行&#xff0c;但是随着次数增加…

day02-前端Web-JavaScript

目录 1. JS介绍2. 引入方式2.1 介绍2.2 演示 3. 基础语法3.1 书写规范3.2 变量3.2.1 let3.2.2 const3.2.3 注意 3.3 数据类型3.4 运算符3.4.1 运算符3.4.2 类型转换 3.5 流程控制语句 4. 函数4.1 格式一4.2 格式二 5. JS对象5.1 基本对象5.1.1 Array对象5.1.1.1 语法格式5.1.1.…

有收到腾讯委托律师事务所向AppStore投诉带有【水印相机】主标题名称App的开发者吗

近期&#xff0c;有多名开发者反馈&#xff0c;收到来自腾讯科技 (深圳) 有限公司委托北京的一家**诚律师事务所卞&#xff0c;写给AppStore的投诉邮件。 邮件内容主要说的是&#xff0c;腾讯注册了【水印相机】这四个字的商标&#xff0c;所以你们这些在AppStore上的app&…

2024年度漏洞态势分析报告,需要访问自取即可!(PDF版本)

2024年度漏洞态势分析报告&#xff0c;需要访问自取即可!(PDF版本),大家有什么好的也可以发一下看看

moviepy 将mp4视频文件提取音频mp3 - python 实现

DataBall 助力快速掌握数据集的信息和使用方式&#xff0c;会员享有 百种数据集&#xff0c;持续增加中。 需要更多数据资源和技术解决方案&#xff0c;知识星球&#xff1a; “DataBall - X 数据球(free)” -------------------------------------------------------------…

算法(二)——一维差分、等差数列差分

文章目录 一维差分、等差数列差分一维差分例题&#xff1a;航班预订统计 等差数列差分例题&#xff1a;三步必杀例题&#xff1a;Lycanthropy 一维差分、等差数列差分 一维差分 差分解决的是 区间修改&#xff08;更新&#xff09;问题&#xff0c;特别是多次区间修改问题&…

深度学习笔记11-优化器对比实验(Tensorflow)

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 一、导入数据并检查 二、配置数据集 三、数据可视化 四、构建模型 五、训练模型 六、模型对比评估 七、总结 一、导入数据并检查 import pathlib,…

FreeROTS学习 内存管理

内存管理是一个系统基本组成部分&#xff0c;FreeRTOS 中大量使用到了内存管理&#xff0c;比如创建任务、信号量、队列等会自动从堆中申请内存&#xff0c;用户应用层代码也可以 FreeRTOS 提供的内存管理函数来申请和释放内存 FreeRTOS 内存管理简介 FreeRTOS 创建任务、队列…

【设计模式】介绍常见的设计模式

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 ✨ 介绍一下常见的设计模式✨ Spring 中常见的设计模式 这期内容主要是总结一下常见的设计模式&#xff0c;可…

6 分布式限流框架

限流的作用 在API对外互联网开放的情况下&#xff0c;是无法控制调用方的行为的。当遇到请求激增或者黑客攻击的情况下&#xff0c;会导致接口占用大量的服务器资源&#xff0c;使得接口响应效率的降低或者超时&#xff0c;更或者导致服务器宕机。 限流是指对应用服务进行限制…

【动态规划篇】欣赏概率论与镜像法融合下,别出心裁探索解答括号序列问题

本篇鸡汤&#xff1a;没有人能替你承受痛苦&#xff0c;也没有人能拿走你的坚强. 欢迎拜访&#xff1a;羑悻的小杀马特.-CSDN博客 本篇主题&#xff1a;带你解答洛谷的括号序列问题&#xff08;绝对巧解&#xff09; 制作日期&#xff1a;2025.01.10 隶属专栏&#xff1a;C/C题…

数据库高安全—角色权限:权限管理权限检查

目录 3.3 权限管理 3.4 权限检查 书接上文数据库高安全—角色权限&#xff1a;角色创建角色管理&#xff0c;从角色创建和角色管理两方面对高斯数据库的角色权限进行了介绍&#xff0c;本篇将从权限管理和权限检查方面继续解读高斯数据库的角色权限。 3.3 权限管理 &#x…

深入浅出负载均衡:理解其原理并选择最适合你的实现方式

负载均衡是一种在多个计算资源&#xff08;如服务器、CPU核心、网络链接等&#xff09;之间分配工作负载的技术&#xff0c;旨在优化资源利用率、提高系统吞吐量和降低响应时间。负载均衡的实现方式多种多样&#xff0c;以下是几种常见的实现方式&#xff1a; 1. 硬件负载均衡&…

Training-free regional prompting for diffusion transformers

通过语言模型来构建位置关系的,omnigen combine来做位置生成,其实可以通过大模型来做,不错。 1.introduction 文生图模型在准确处理具有复杂空间布局的提示时仍然面临挑战,1.通过自然语言准确描述特定的空间布局非常困难,特别是当对象数量增加或需要精确的位置控制时,2.…

麦田物语学习笔记:背包物品选择高亮显示和动画

如题,本篇文章没讲动画效果 基本流程 1.代码思路 (1)先用点击事件的接口函数去实现,点击后反转选择状态(isSelected),以及设置激活状态(SetActive),并且还需要判断该格子是否为空,空格子是点不动的,完成后以上后,出现的问题是高亮应该是有且仅有一个格子是高亮的,而现在可以让…

Linux:深入了解fd文件描述符

目录 1. 文件分类 2. IO函数 2.1 fopen读写模式 2.2 重定向 2.3 标准文件流 3. 系统调用 3.1 open函数认识 3.2 open函数使用 3.3 close函数 3.4 write函数 3.5 read函数 4. fd文件描述符 4.1 标准输入输出 4.2 什么是文件描述符 4.3 语言级文件操作 1. 文件分类…

数据结构:栈(Stack)和队列(Queue)—面试题(一)

目录 1、括号匹配 2、逆波兰表达式求值 3、栈的压入、弹出序列 4、最小栈 1、括号匹配 习题链接https://leetcode.cn/problems/valid-parentheses/description/ 描述&#xff1a; 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] …