当前位置: 首页 > news >正文

创建线程池和封装锁

封装一个锁

1.封装一个Mutex

class Mutex{public:Mutex(pthread_mutex_t * lock):_lock(lock){}void Lock(){pthread_mutex_lock(_lock);}void unLock(){pthread_mutex_unlock(_lock);}~Mutex(){}private:pthread_mutex_t *_lock;
};

2.封装一个LockGuard

class LockGuard{public:LockGuard(pthread_mutex_t * lock):_mutex(lock){_mutex.Lock();}~LockGuard(){_mutex.unLock();}private:Mutex _mutex;
};

在底层就可以直接创建一个LockGuard对象,就可以直接对临时资源进行加锁

类似:

​
{LockGuard(&mutex);//临界资源}​

创建线程池

封装线程

1.成员变量

private:std::string _threadname;pthread_t _pid;func_t<T> _func;bool _isrunning;T _data;
template <class T>
using func_t = std::function<void(T&)>;

我们创建一个fun_t 用来传递一个函数给线程,在内部用来回调。

2.构造函数

  Thread(std::string threadname, func_t<T> func, T& data): _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data){}

3.Start函数和Join函数

 bool Start(){int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);if (n == 0){_isrunning = true;return true;}return false;}bool Join(){if(!_isrunning) return true;int n=pthread_join(_pid,nullptr);if(n==0){_isrunning=false;return true;}else{return false;}}

4.在创建线程传递一个ThreadRoution函数

static void *ThreadRoutine(void *args) // 类内方法,{// (void)args; // 仅仅是为了防止编译器有告警Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}

ThreadRountion可不可以为类内函数?

不可以,类内函数默认隐藏的传递this指针,我们必须设置为静态函数函数,再传递this指针。

#pragma once#include <iostream>
#include <pthread.h>
#include <functional>
#include <cstring>template <class T>
using func_t = std::function<void(T&)>;template <class T>
class Thread
{
public:Thread(std::string threadname, func_t<T> func, T& data): _threadname(threadname), _pid(0), _func(func), _isrunning(false), _data(data){}static void *ThreadRoutine(void *args) // 类内方法,{// (void)args; // 仅仅是为了防止编译器有告警Thread *ts = static_cast<Thread *>(args);ts->_func(ts->_data);return nullptr;}bool Start(){int n = pthread_create(&_pid, nullptr, ThreadRoutine, this);if (n == 0){_isrunning = true;return true;}return false;}bool Join(){if(!_isrunning) return true;int n=pthread_join(_pid,nullptr);if(n==0){_isrunning=false;return true;}else{return false;}}const std::string& Threadname(){return _threadname;} private:std::string _threadname;pthread_t _pid;func_t<T> _func;bool _isrunning;T _data;
};

创建线程池

我们打算用queue来储存任务,用vector数组储存线程

当任务队列为空时,我们用条件变量去控制线程睡眠,队列Push进任务再控制线程醒来。

1.成员变量

private:queue<T> _taskq;vector<Thread<ThreadData>> _ptdv;pthread_mutex_t _mutex;pthread_cond_t _cond;int _thread_num;

2.构造函数

初始化锁,条件变量,并创建线程。

  pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);for (int i = 1; i <= defaultthreadnum; i++){string threadname("thread-");threadname += to_string(i);ThreadData td(threadname);Thread<ThreadData> t(threadname,std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);_ptdv.push_back(t);lg.LogMessage(Info, "%s is created...\n", threadname.c_str());}}

任务队列为空,让所有线程休眠,队列中有任务,直接让线程执行任务:t()

void pthread_Run(ThreadData &data){while (true){T t;{LockGuard ld(&_mutex);if (_taskq.empty()){allthreadsleep(data);}t = _taskq.front();_taskq.pop();}t();{LockGuard ld(&_mutex);lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());}}}

3.进程唤醒与进程休眠

void allthreadwakeup(){pthread_cond_signal(&_cond);}
void allthreadsleep(const ThreadData &data){lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());pthread_cond_wait(&_cond, &_mutex);}

4.Push()

    void Push(T &task){{LockGuard ld(&_mutex);_taskq.push(task);// 插入任务后唤醒进程allthreadwakeup();}}
#pragma once
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include <cstring>
#include <functional>
#include <unistd.h>
#include "pthread.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"
using namespace std;
static const int defaultthreadnum = 5;template <class T>
using func_r = std::function<void(T)>;class ThreadData
{
public:ThreadData(string name) : _name(name){}~ThreadData(){}public:string _name;
};
template <class T>
class pthread_pool
{
public:static pthread_pool<T> *Getinstance(){if (instance == nullptr){pthread_mutex_lock(&_sig_ins);if (instance == nullptr){instance = new pthread_pool<T>(defaultthreadnum);lg.LogMessage(Info, "instance is create succeess...\n");return instance;}}}pthread_pool(int thread_num = defaultthreadnum) : _thread_num(thread_num){pthread_mutex_init(&_mutex, nullptr);pthread_cond_init(&_cond, nullptr);for (int i = 1; i <= defaultthreadnum; i++){string threadname("thread-");threadname += to_string(i);ThreadData td(threadname);Thread<ThreadData> t(threadname,std::bind(&pthread_pool<T>::pthread_Run, this, std::placeholders::_1), td);_ptdv.push_back(t);lg.LogMessage(Info, "%s is created...\n", threadname.c_str());}}pthread_pool(const pthread_pool<T> &pp) = delete;const pthread_pool<T> &operator=(const pthread_pool<T> &pp) = delete;void allthreadwakeup(){pthread_cond_signal(&_cond);}void allthreadsleep(const ThreadData &data){lg.LogMessage(Debug, "no task, %s is sleeping...\n", data._name.c_str());pthread_cond_wait(&_cond, &_mutex);}void pthread_Run(ThreadData &data){while (true){T t;{LockGuard ld(&_mutex);if (_taskq.empty()){allthreadsleep(data);}t = _taskq.front();_taskq.pop();}t();{LockGuard ld(&_mutex);lg.LogMessage(Info, "Thread name:%s is handling: %s \n", data._name.c_str(), t.PrintTask().c_str());lg.LogMessage(Info, "Thread name:%s get result: %s \n", data._name.c_str(), t.PrintResult().c_str());}}}void Start(){for (auto &th : _ptdv){th.Start();lg.LogMessage(Info, "%s is running ...\n", th.Threadname().c_str());}}void Push(T &task){{LockGuard ld(&_mutex);_taskq.push(task);// 插入任务后唤醒进程allthreadwakeup();}}// Just for debug success!void Wait(){for (auto &th : _ptdv){th.Join();}}~pthread_pool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond);}private:queue<T> _taskq;vector<Thread<ThreadData>> _ptdv;pthread_mutex_t _mutex;pthread_cond_t _cond;int _thread_num;static pthread_pool *instance;static pthread_mutex_t _sig_ins;
};
template <class T>
pthread_pool<T> *pthread_pool<T>::instance = nullptr;
template <class T>
pthread_mutex_t pthread_pool<T>::_sig_ins = PTHREAD_MUTEX_INITIALIZER;

线程池单利化问题

  static pthread_pool<T> *Getinstance(){if (instance == nullptr){pthread_mutex_lock(&_sig_ins);if (instance == nullptr){instance = new pthread_pool<T>(defaultthreadnum);lg.LogMessage(Info, "instance is create succeess...\n");return instance;}}}

在获取单例的函数中,我们是需要加锁的,防止多个线程同时进入创建出多个单利。

http://www.lryc.cn/news/458163.html

相关文章:

  • 易图讯军用VR三维电子沙盘系统
  • LeetCode讲解篇之70. 爬楼梯
  • 论文写作不再难,论文初稿快速成型法!
  • linux系统,监控进程运行状态并自动重启崩溃后的进程的多种方法
  • 【JavaEE初阶】深入理解不同锁的意义,synchronized的加锁过程理解以及CAS的原子性实现(面试经典题);
  • 详解Redis分布式锁在SpringBoot的@Async方法中没锁住的坑
  • 怎么做接口自动化测试
  • 网络编程(18)——使用asio协程实现并发服务器
  • Koa2项目实战2(路由管理、项目结构优化)
  • 决战Linux操作系统
  • OceanBase 3.2.2 数据库问题处理记录
  • HCIP--以太网交换安全(二)端口安全
  • 在 Windows 11 安卓子系统中安装 APK 的操作指南
  • [C语言] 函数详解:库函数与自定义函数
  • 0x11 科迈 RAS系统 Cookie验证越权漏洞
  • MoonBit 双周报 Vol.57:AI助手功能增强、表达式优先级调整、JS 交互优化、标准库与实验库API多项更新!
  • element ui input textarea控制显示高度
  • Chromium 中chrome.downloads扩展接口c++
  • 微信小程序常见问题
  • 进程的理解
  • LeetCode494:目标和
  • vue3中自定义校验函数密码不生效问题
  • RabbitMQ(死信队列)
  • HTTP代理的优点和局限性
  • 大厂面试真题-如果通过JVM自带的工具排查和解决线上CPU100%的问题
  • kubernetes中微服务部署
  • 基于 Java 的天气预报系统设计与实现
  • 思迅商云8前台打开提示上传日志信息失败
  • webstorm的缩进设置(过度缩进解释)
  • 与ZoomEye功能类似的搜索引擎还有哪些?(渗透课作业)