【Linux】基于单例模式懒汉实现方式的线程池

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

一、LockGuard.hpp

#pragma once
#include <iostream>
#include <pthread.h>
class Mutex//锁的对象
{
public:Mutex(pthread_mutex_t* lock_p=nullptr):_lock_p(lock_p){}~Mutex(){}void lock(){if(_lock_p){pthread_mutex_lock(_lock_p);}}void unlock(){if(_lock_p){pthread_mutex_unlock(_lock_p);}}
private:pthread_mutex_t* _lock_p;//锁的指针
};
class LockGuard//加锁和解锁的类
{
public:LockGuard(pthread_mutex_t* mutex):_mutex(mutex){_mutex.lock();//在构造函数进行加锁}~LockGuard(){_mutex.unlock();//在析构函数进行解锁}
private:Mutex _mutex;
};

二、Task.hpp

#pragma once
#include <iostream>
#include <functional>
#include <string>
class Task
{//using func=std::function<int(int,int,char)>;typedef std::function<int(int,int,char)> func_t;//函数对象
public:Task(){}Task(int x,int y,char op,func_t func):_x(x),_y(y),_op(op),_callBack(func){}std::string operator()()//消费者调用{int result=_callBack(_x,_y,_op);char buffer[1024];snprintf(buffer,sizeof(buffer),"%d %c %d=%d",_x,_op,_y,result);//结果字符串return buffer;}std::string toTaskString()//生产者调用{char buffer[1024];snprintf(buffer,sizeof(buffer),"%d %c %d=?",_x,_op,_y);return buffer;}
private:int _x;int _y;char _op;//加减乘除取模func_t _callBack;//回调函数
};const std::string oper = "+-*/%";
int myMath(int x, int y, char op)
{int result = 0;switch (op){case '+':result = x + y;break;case '-':result = x - y;break;case '*':result = x * y;break;case '/':{if (y == 0){std::cerr << "div zero error" << std::endl;result = -1;}elseresult = x / y;}break;case '%':{if (y == 0){std::cerr << "mod zero" << std::endl;result = -1;}elseresult = x % y;}break;default:std::cout<<"运算符输入有误"<<std::endl;break;}return result;
}

三、Thread.hpp

#pragma once
#include <iostream>
#include <pthread.h>
#include <string>
#include <functional>
#include <cassert>
namespace ThreadNs
{typedef std::function<void*(void*)> func_t;//定义一个函数对象类型,它的返回值和参数都是void*const int num = 1024;class Thread{private://因为形参有个this指针,所以弄成staticstatic void* start_routine(void* args)//这里的args就是 start()的ctx{Thread* _this=static_cast<Thread*>(args);return _this->callback();} void* callback(){return _func(_args);}public://构造函数Thread(){char nameBuffer[num];snprintf(nameBuffer,sizeof(nameBuffer),"thread-%d",threadNum++);_name=nameBuffer;}void start(func_t func,void* args=nullptr)//线程启动{_func=func;_args=args;int n=pthread_create(&_tid,nullptr,start_routine,this);assert(n==0);(void)n;}void join(){int n=pthread_join(_tid,nullptr);assert(n==0);(void)n;}std::string threadName(){return _name;}~Thread(){}private:std::string _name;//线程的名字func_t _func;//线程的回调函数void* _args;//喂给线程的参数pthread_t _tid;//线程IDstatic int threadNum;//线程编号,最好自己再加个锁};int Thread::threadNum=1;//异常和if。意料之外//assert。意料之中。99%概率为真。
}

四、ThreadPool.hpp

#pragma once
#include <vector>
#include <queue>
#include <pthread.h>
#include <unistd.h>
#include <mutex>
#include "Thread.hpp"
#include "LockGuard.hpp"
using namespace ThreadNs;
const int gnum =5;template <class T>//声明
class ThreadPool;template <class T>
struct ThreadData
{ThreadData(ThreadPool<T>* tp,const std::string& s):_threadPool(tp),_name(s){}ThreadPool<T>* _threadPool;std::string _name;
};
template <class T>
class ThreadPool
{
private://因为普通成员函数第一个参数是this指针,和回调方法不匹配,故改成static类型static void* handlerTask(void* args)//args是ThreadData对象指针{ThreadData<T>* td=static_cast<ThreadData<T>*>(args);while(1){T t;{   //RAII,出了作用域LockGuard会销毁,将析构锁LockGuard lockGuard(td->_threadPool->mutex());//加锁while(td->_threadPool->IsQueueEmpty())//如果队列为空,则等待{td->_threadPool->ThreadWait();}//线程能走到这里,说明队列一定有任务给线程t=td->_threadPool->Pop();//从队列中取出任务}std::cout<<td->_name<<"已获取任务:"<<t.toTaskString()<<"处理结果是:"<<t()<<std::endl;//处理任务,这个任务放到线程的外面}delete td;//析构ThreadData对象return nullptr;}ThreadPool(const int& num=gnum):_num(num){pthread_mutex_init(&_mutex,nullptr);pthread_cond_init(&_cond,nullptr);//创建线程for(int i=0;i<_num;++i){_threads.push_back(new Thread());}}ThreadPool(const ThreadPool<T>&)=delete;//禁用拷贝构造ThreadPool<T>& operator=(const ThreadPool<T>&)=delete;//禁用赋值运算符重载public://解决静态handlerTask是静态函数的问题,这几个都是偷家函数void LockQueue()   {pthread_mutex_lock(&_mutex);}void UnLockQueue() {pthread_mutex_unlock(&_mutex);}bool IsQueueEmpty(){return _taskQueue.empty();}void ThreadWait()  {pthread_cond_wait(&_cond,&_mutex);}T Pop()         {T t=_taskQueue.front();_taskQueue.pop();return t;} pthread_mutex_t* mutex(){return &_mutex;}
public: void run()//线程启动{for(const auto& t:_threads){ThreadData<T>* td=new ThreadData<T>(this,t->threadName());t->start(handlerTask,(void*)td);std::cout<<t->threadName()<<"start..."<<std::endl;}}void push(const T& in){//RAII,出了作用域,锁将会被释放LockGuard lockGuard(&_mutex);_taskQueue.push(in);pthread_cond_signal(&_cond);std::cout<<"任务发送成功"<<std::endl;}~ThreadPool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);for(const auto& t:_threads){delete t;}}static ThreadPool<T>* getInstance()//这里的static的作用是让这个函数只有一份,获取单例对象。tp是临界资源,需要加锁{if(nullptr==tp)//因为锁只创建一次,防止线程进来被锁阻塞{//只进来一次就够了_singletonLock.lock();if(nullptr==tp)//说明对象还没有被创建{tp=new ThreadPool<T>(); }_singletonLock.unlock();}return tp;}
private:int _num;//线程个数std::vector<Thread*> _threads;//使用vector存放线程std::queue<T> _taskQueue;//任务队列,往里面放任务,它是共享资源,需要加锁保护pthread_mutex_t _mutex;//互斥锁pthread_cond_t _cond;//条件变量static ThreadPool<T>* tp;//单例模式静态的对象指针static std::mutex _singletonLock;//获取单例对象使用的锁};
template <class T>
ThreadPool<T>* ThreadPool<T>::tp=nullptr;template <class T>
std::mutex ThreadPool<T>::_singletonLock;

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

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

相关文章

FastAPI使用ORJSONResponse作为默认的响应类型

FastAPI默认使用Python的标准库来做json解析&#xff0c;如果换成rust编写的orjson&#xff0c;速度上会快一些 1. 安装依赖 pip install orjson 2. 设置为默认响应类型 from fastapi.responses import ORJSONResponseapp FastAPI(titlexxx, default_response_classORJSON…

nginx+flask+Gunicorn反代理服务拿不到真实IP的解决

背景 本人在宝塔linux环境&#xff0c;要部署flask的简单后端并且用Ngnix反代理&#xff0c;用Gunicorn框架部署。&#xff08;o(╥﹏╥)o中间磕磕绊绊总算部署上去了&#xff0c;需要了解Gunicorn怎么部署的朋友&#xff0c;评论区留言&#xff0c;我加补一篇介绍&#xff09;…

32I2C通信协议

异步时序的&#xff1a;非常依赖硬件外设的支持&#xff0c;比如串口是很难用软件来模拟的&#xff1b;但节省了一根时钟线的资源 同步时序可以极大地降低单片机对硬件电路的依赖&#xff0c;时钟线停止了&#xff0c;发送方和接收方都会停止 一.I2C通信协议简介 二.硬件电路…

[WUSTCTF2020]朴实无华(特详解)

一开始说header出问题了 就先dirsaerch扫一遍 发现robot.txt 访问一下 去看看&#xff0c;好好好&#xff0c;肯定不是得 他一开始说header有问题&#xff0c;不妨抓包看看&#xff0c;果然有东西 访问看看&#xff0c;乱码修复一下&#xff0c;在之前的博客到过 <img src…

Mysql——更新数据

注&#xff1a;文章参考&#xff1a; MySQL 更新数据 不同条件(批量)更新不同值_update批量更新同一列不同值-CSDN博客文章浏览阅读2w次&#xff0c;点赞20次&#xff0c;收藏70次。一般在更新时会遇到以下场景&#xff1a;1.全部更新&#xff1b;2.根据条件更新字段中的某部分…

div 2_div 3_ div 4_刷题刷题刷题

关于 div 4 的思考 感觉好像可以写到 F 都不需要什么算法知识 关于 div 3 的思考 感觉可以做到 E 好像都不需要什么算法知识 关于 div 2 的思考 好像做到 C 都不需要什么算法知识 赶紧刷题就行&#xff0c;加油加油

【C++】实现一个二叉搜索树

目录 二叉搜索树的概念 1.结点定义 2.构造、析构、拷贝构造、赋值重载 3.插入、删除、查找、排序 3.1插入 3.2插入递归版 3.3查找指定值 3.3查找指定值递归版 3.4中序遍历 3.5删除 最后 二叉搜索树的概念 二叉搜索树又称为二叉排序树或二叉查找树&#xff0c;它或者…

Markdown:简洁高效的文本标记语言

引言 在当今信息爆炸的时代&#xff0c;我们需要一种简洁、高效的文本标记语言来排版和发布内容。Markdown应运而生&#xff0c;它是一种轻量级的文本标记语言&#xff0c;以其简单易学、易读易写的特点&#xff0c;成为了广大写作者的首选工具。本文将介绍Markdown的语法优缺…

设计模式(行为型模式)观察者模式

目录 一、简介二、观察者模式2.1、事件接口及其实现2.2、观察者接口及其实现2.3、主题接口及其实现2.4、使用 三、优点与缺点 一、简介 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一种一对多的依赖关系&#xff0c;当一个对象…

Composition Local

1.显示传参 package com.jmj.jetpackcomposecompositionlocalimport org.junit.Testimport org.junit.Assert.*/*** 显示传参*/ class ExplicitText {private fun Layout(){var color:String "黑色";//参数需要通过层层传递&#xff0c;比较繁琐Text(color)Grid(c…

B2081 与 7 无关的数(洛谷)

题目描述 一个正整数&#xff0c;如果它能被 7 整除&#xff0c;或者它的十进制表示法中某一位上的数字为 7&#xff0c;则称其为与 7 相关的数。现求所有小于等于 n(n<100) 与 7 无关的正整数的平方和。 输入格式 输入为一行&#xff0c;正整数 n(n<100)。 输出格式…

Redis篇之过期淘汰策略

一、数据的过期策略 1.什么是过期策略 Redis对数据设置数据的有效时间&#xff0c;数据过期以后&#xff0c;就需要将数据从内存中删除掉。可以按照不同的规则进行删除&#xff0c;这种删除规则就被称之为数据的删除策略&#xff08;数据过期策略&#xff09;。 2.过期策略-惰…

rem基础+媒体查询+Less基础

一&#xff0c;rem基础 二&#xff0c;媒体查询 2.1什么是媒体查询 2.2语法规范 2.3媒体查询rem实现元素动态大小的变化 2.4 引入资源&#xff08;理解&#xff09; 三&#xff0c;Less基础 1 维护css的弊端 2 Less介绍 3 Less变量 变量命名规范 4 Less嵌套 5 Less…

2021年通信工程师初级 实务 真题

文章目录 一、第1章 现代通信网概述&#xff0c;通信网的定义。第10章 通信业务&#xff0c;普遍服务原则10.2.4 通信行业的发展趋势&#xff08;六化&#xff09; 二、第2章 传输网SDH帧结构SDH线路保护倒换&#xff0c;“11 保护”和“1:1保护”波长值λc/f&#xff0c;中心频…

思科模拟器命令大全详解

以下是常用的Cisco模拟器&#xff08;如Packet Tracer&#xff09;中的命令大全详解&#xff1a; 1. 基础命令 - enable&#xff1a;进入特权模式&#xff08;enable mode&#xff09;。 - configure terminal&#xff1a;进入全局配置模式&#xff08;global configuration …

鸿蒙开发-UI-图形-图片

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 文章目录 一、基本概念 二、图片资源加载 1. 存档图类型数据源 2.多媒体像素图 三、显示矢量图 四、图片…

LLM大语言模型(六):RAG模式下基于PostgreSQL pgvector插件实现vector向量相似性检索

目录 HightLightMac上安装PostgreSQLDBever图形界面管理端创建DB 使用向量检索vector相似度计算近似近邻索引HNSW近似近邻索引示例 HightLight 使用PostgreSQL来存储和检索vector&#xff0c;在数据规模非庞大的情况下&#xff0c;简单高效。 可以和在线业务共用一套DB&#…

在 Ubuntu 22.04 上安装 Django Web 框架的方法

简介 Django 是一个功能齐全的 Python Web 框架&#xff0c;用于开发动态网站和应用程序。使用 Django&#xff0c;您可以快速创建 Python Web 应用程序&#xff0c;并依赖框架来完成大部分繁重的工作。 在本指南中&#xff0c;您将在 Ubuntu 22.04 服务器上启动 Django。安装…

【动态规划】【C++算法】2188. 完成比赛的最少时间

作者推荐 【动态规划】【前缀和】【C算法】LCP 57. 打地鼠 本文涉及知识点 动态规划汇总 LeetCode2188. 完成比赛的最少时间 给你一个下标从 0 开始的二维整数数组 tires &#xff0c;其中 tires[i] [fi, ri] 表示第 i 种轮胎如果连续使用&#xff0c;第 x 圈需要耗时 fi…

Xshell

更改背景颜色 多个会话同时执行命令 查看 -> 撰写 -> 撰写窗格