linux线程池模拟实现

今天模拟实现了个线程池,怎么说,感觉整体还是比较容易的,线程池和内存池,进程池等等,大概就是一个意思,例如内存池,就是提前申请好内存,然后等你用的时候再去其中拿就可以了,线程池是一个道理,就是现申请好一个,等我们有任务时,去让线程取任务。代码如下:

#pragma once
#include <iostream>
#include <pthread.h>
#include <vector>
#include <queue>
#include <unistd.h>
#include "thread.hpp"
#include "myMtx.hpp"
#include "cond.hpp"
using namespace std;
#define NUMPTHREAD 5
#define NUMTAK 5
typedef void *(*func)(void *);
//饿汉单列模型
template <class T>
class pthreadPool
{
public:static pthreadPool<T> *get(){return _mypool;}private:pthreadPool(int nump = NUMPTHREAD, int numt = NUMTAK) : _numpthread_t(nump), _tasknum(numt){pthread_cond_init(&_full, nullptr);pthread_cond_init(&_empty, nullptr);pthread_mutex_init(&_mtx, nullptr);}public:void start(){_func = pthreadPool<T>::enter;for (int i = 0; i < _numpthread_t; i++){thread *p = new thread(_func, this);_pthread_t.push_back(p);}}void pop(T &x){myMtx mtx(_mtx);myCond me(_empty, _mtx);myCond mf(_full, _mtx);while (_task.size() == 0){mf.singal();me.wait();}sleep(5);cout << "消费" << pthread_self() << endl;x = _task.front();_task.pop();}static void *enter(void *args){pthreadPool<T> *td = reinterpret_cast<pthreadPool<T> *>(args);while (true){T ret;td->pop(ret);cout << ret << endl;}return nullptr;}// 插入任务void task(const T &x){myMtx m(_mtx);myCond me(_empty, _mtx);myCond mf(_full, _mtx);while (_task.size() == _tasknum){me.singal();mf.wait();}cout << "生产" << pthread_self() << endl;sleep(5);_task.push(x);}~pthreadPool(){pthread_cond_destroy(&_full);pthread_cond_destroy(&_empty);pthread_mutex_destroy(&_mtx);for (auto &e : _pthread_t)delete e;}private:vector<thread *> _pthread_t;queue<T> _task;func _func;int _numpthread_t;int _tasknum;pthread_mutex_t _mtx;pthread_cond_t _full;pthread_cond_t _empty;static pthreadPool<T> *_mypool;
};
template <class T>
class pthreadPool;
template <class T>
pthreadPool<T> *pthreadPool<T>::_mypool = new pthreadPool<T>();
#pragma once
#include <iostream>
#include <pthread.h>
class myCond
{
public:myCond(pthread_cond_t &cond, pthread_mutex_t &mtx) : _mcond(cond), _mtx(mtx){}void wait(){pthread_cond_wait(&_mcond,&_mtx);}void singal(){pthread_cond_signal(&_mcond);}
private:pthread_cond_t &_mcond;pthread_mutex_t &_mtx;
};
#pragma once
#include <iostream>
#include <pthread.h>
class myMtx
{
public:myMtx(pthread_mutex_t &mtx) : _mtx(mtx){pthread_mutex_lock(&_mtx);std::cout << "加锁" << std::endl;}~myMtx(){pthread_mutex_unlock(&_mtx);std::cout << "解锁" << std::endl;}private:pthread_mutex_t &_mtx;
};
#pragma once
#include <iostream>
#include <pthread.h>
class myMtx
{
public:myMtx(pthread_mutex_t &mtx) : _mtx(mtx){pthread_mutex_lock(&_mtx);std::cout << "加锁" << std::endl;}~myMtx(){pthread_mutex_unlock(&_mtx);std::cout << "解锁" << std::endl;}private:pthread_mutex_t &_mtx;
};
#include "pthreadPool.hpp"
#include <time.h>int main()
{srand((size_t)time(nullptr) ^ 1100 + 1);pthreadPool<int> *p = pthreadPool<int>::get();p->start();while (true){p->task(rand() % 100 + 1);cout << "插入成功" << endl;}delete p;return 0;
}

总体实现如上,逻辑还是比较像生产消费模型的,总体进行了锁的封装,没有写打印日志的函数。

实现的时候,个人认为可以放任务的队列实现成static,如果实现成static的话,那么此时的所有对象只有一个任务队列,但是话又说回来,如果创建多个线程池的对象,那么就只有一个任务队列,貌似也不符合逻辑,有这种想法的其实错了,因为线程池就像内存池一样,只有一个,所以我最后把其设计成了单列模式,用的是饿汉模式,因为饿汉模式没有线程安全问题,所以我用了饿汉模式实现你的单利。这只是个人想法,也可以不用把任务队列实现为static。

然后锁和条件变量都是用RAII的风格来实现的,这样看代码比较简洁。

实现的注意事项,个人认为还是线程访问任务队列的哪里比较绕,因为我的每一个线程是封装了的,所以他创建线程是调用的函数必须是静态的,但是如果这个函数是静态的话,那么此时他就不可以访问其他的成员变量了,所以此时必须要传this指针才可以,有些伙伴可能想的是不封装线程,不封装线程其实是一样的,如果你把创建线程的函数实现在类内,那么就不可以调用,也必须是静态成员函数才可以,如果实现在类外,因为函数中要访问其内部的成员,所以此时必须是友元函数才可以,但是此时问题又来了,因为我们线程池的实现是模版,所以你必须把这个函数也实现为模版类型,所以,这里一定要注意。

以上就是我实现的过程,想看源码的朋友可以点这里https://gitee.com/stickykkkkkk/linux/tree/master/dm11-13

最后希望大家能够支持,谢谢!!!

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

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

相关文章

SecureCRT 超时自动断开连接问题解决方法

很多人在使用SecureCRT时&#xff0c;会遇到这种情况&#xff1a;SecureCRT 超时自动断开连接&#xff0c;这种情况会给工作带来很多不便&#xff0c; 比如在做数据库还原操作时&#xff0c;连接突然断掉了&#xff0c;会导致还原操作失败&#xff0c;很是令人困扰。 那么我们…

JVS低代码表单自定义按钮的使用说明和操作示例

在普通的表单设计中&#xff0c;虽然自带的【提交】、【重置】、【取消】按钮可以满足基本操作需求&#xff0c;但在面对更多复杂的业务场景时&#xff0c;这些按钮的显示控制就显得有些力不从心。为了更好地满足用户在表单操作过程中的个性化需求&#xff0c;JVS低代码推出了表…

nohup命令 不挂断执行shell脚本,终端退出后进程被关闭

在微调Qwen大模型的时候&#xff0c;由于训练时间比较长&#xff0c;因此使用nohup命令想把用于训练的shell脚本挂在后台不挂断运行&#xff0c;想着即使是liunx终端关闭&#xff0c;也能在后台训练。 我使用FinalShell连接Linux服务器&#xff0c;最初使用 nohup sh finetun…

【优化版】DOSBox及常用汇编工具的详细安装教程

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、图解数据结构 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. dosbox的介绍、下载和安装1.1 dosbos简介1.2 dosbox的下载1.2.1 方式一&a…

Java16新增特性

前言 前面的文章&#xff0c;我们对Java9、Java10、Java11、Java12 、Java13、Java14、Java15 的特性进行了介绍&#xff0c;对应的文章如下 Java9新增特性 Java10新增特性 Java11新增特性 Java12新增特性 Java13新增特性 Java14新增特性 Java15新增特性 今天我们来一起看一下…

用excel计算一个矩阵的转置矩阵

假设我们的原矩阵是一个3*3的矩阵&#xff1a; 125346789 现在求它的转置矩阵&#xff1a; 鼠标点到一个空白的地方&#xff0c;用来存放结果&#xff1a; 插入-》函数&#xff1a; 选择TRANSPOSE&#xff0c;这个就是求转置矩阵的函数&#xff1a; 点击“继续”&#xff1a…

2. 深度学习——初始化方法

机器学习面试题汇总与解析——初始化方法 本章讲解知识点 什么是初始化方法为什么需要合理的参数初始化详细讲解初始化方法本专栏适合于Python已经入门的学生或人士,有一定的编程基础。本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。本专栏针对面试题答案进行…

交叉编译 openssl

要在 x86 平台上编译适用于 aarch64 架构的 OpenSSL 动态库&#xff0c;你需要使用交叉编译工具链。可以按照以下步骤进行&#xff1a; 安装 aarch64 交叉编译工具链&#xff1a; $ sudo apt-get install gcc-aarch64-linux-gnu g-aarch64-linux-gnu 这将安装 aarch64 交叉编…

元核云亮相金博会,智能质检助力金融合规

11月初&#xff0c;第五届中新&#xff08;苏州&#xff09;数字金融应用博览会&#xff5c;2023金融科技大会在苏州国际博览中心举办&#xff0c;围绕金融科技发展热点领域及金融行业信息科技领域重点工作&#xff0c;分享优秀实践经验&#xff0c;探讨数字化转型路径与未来发…

简单理解Vue2的响应式原理

使用Vue作为前端开发技术栈的同学&#xff0c;在使用Vue时都会有一些好奇&#xff1a;为啥我们的响应式变量要在data中定义&#xff1f;Vue是如何监听到变化&#xff0c;实现响应式的&#xff1f;这次我们就来探究一下&#xff0c;Vue2的响应式原理。 对象的响应式 修改属性描…

Ubuntu 20.04 DNS解析原理, 解决resolv.conf被覆盖问题

------------------------------------------------------------------ author: hjjdebug date: 2023年 11月 09日 星期四 14:01:11 CST description: Ubuntu 20.04 DNS解析原理, 解决resolv.conf被覆盖问题 ----------------------------------------------------------------…

(三)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

【Copilot】登录报错 Extension activation failed: “No auth flow succeeded.“(VSCode)

问题描述 当尝试在 Visual Studio Code 中登录 GitHub Copilot 插件时&#xff0c;会出现报错的情况&#xff0c;如下图所示&#xff1a; 尽管在浏览器中成功授权了 GitHub 账户&#xff0c;但在返回 VSCode 后仍然报错&#xff0c;如下图所示&#xff1a; 同时&#xff0c;在…

PHP中传值与引用的区别

在PHP中&#xff0c;变量的传递方式主要分为传值和传引用两种。这两种方式在操作中有一些重要的区别&#xff0c;影响着变量在函数调用或赋值操作中的表现。下面详细解释一下这两种传递方式的区别。 传值&#xff08;By Value&#xff09; 传值是指将变量的值复制一份传递给函…

OpenAtom OpenHarmony三方库创建发布及安全隐私检测

OpenAtom OpenHarmony三方库&#xff08;以下简称“三方库”或“包”&#xff09;&#xff0c;是经过验证可在OpenHarmony系统上可重复使用的软件组件&#xff0c;可帮助开发者快速开发OpenHarmony应用。三方库根据其开发语言分为2种&#xff0c;一种是使用JavaScript和TypeScr…

分成互质组——DFS

给定 n 个正整数&#xff0c;将它们分组&#xff0c;使得每组中任意两个数互质。至少要分成多少个组&#xff1f; 输入格式 第一行是一个正整数 n。 第二行是 n 个不大于10000的正整数。 输出格式 一个正整数&#xff0c;即最少需要的组数。 数据范围 1≤n≤10 输入样例&am…

React【异步逻辑createAsyncThunk(一)、createAsyncThunk(二)、性能优化、createSelector】(十二)

文章目录 异步逻辑 createAsyncThunk&#xff08;一&#xff09; createAsyncThunk&#xff08;二&#xff09; 性能优化 createSelector 异步逻辑 //Product.js const onAdd () > {const name nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name…

3D Gaussian Splatting:用于实时的辐射场渲染

Kerbl B, Kopanas G, Leimkhler T, et al. 3d gaussian splatting for real-time radiance field rendering[J]. ACM Transactions on Graphics (ToG), 2023, 42(4): 1-14. 3D Gaussian Splatting 是 Siggraph 2023 的 Best Paper&#xff0c;法国团队在会议上展示了其实现的最…

线性代数(二)| 行列式性质 求值 特殊行列式 加边法 归纳法等多种方法

文章目录 1. 性质1.1 重要性质梳理1.1.1 转置和初等变换1.1.2加法行列式可拆分1.1.3 乘积行列式可拆分 1.2 行列式性质的应用1.2.1 简化运算1.2.2 将行列式转换为&#xff08;二&#xff09;中的特殊行列式 2 特殊行列式2.1 上三角或下三角行列式2.2 三叉行列式2.3 行列式行和&…

VueCli 自定义创建项目及配置

一、VueCli 自定义创建项目 1.安装脚手架 (已安装) npm i vue/cli -g2.创建项目 vue create hm-exp-mobile选项 Vue CLI v5.0.8 ? Please pick a preset:Default ([Vue 3] babel, eslint)Default ([Vue 2] babel, eslint) > Manually select features 选自定义手动…