🌈C++专栏: 南桥谈C++
🌈C语言专栏: C语言学习系列
🌈Linux学习专栏: 南桥谈Linux
🌈数据结构学习专栏: 数据结构杂谈
🌈数据库学习专栏: 南桥谈MySQL
🌈Qt学习专栏: 南桥谈Qt
🌈菜鸡代码练习: 练习随想记录
🌈git学习: 南桥谈Git
原理
在一个可执行程序内部存在多个线程和一个任务队列。如果任务队列里长时间没有任务,这些线程就会休眠,如果此时来了一个任务,那么线程就会被唤醒。像这种,提前创建好线程,需要的时候直接使用,我们称之为线程池。这种本质上就是一个生产消费模型。
线程池实现
//ThreadPool.hpp
#pragma once
#include<iostream>
#include<unistd.h>
#include<string>
#include<vector>
#include<queue>
#include<functional>
#include"Thread.hpp"
using namespace threadModel;
static const int gdefaultnum=5;
void test()
{
while(true)
{
std::cout<<"hello world"<<std::endl;
sleep(1);
}
}
template<typename T>
class ThreadPool
{
private:
void LockQueue()
{
pthread_mutex_lock(&_mutex);
}
void UnlockQueue()
{
pthread_mutex_unlock(&_mutex);
}
void Wakeup()
{
pthread_cond_signal(&_cond);
}
void WakeupAll()
{
pthread_cond_broadcast(&_cond);
}
void Sleep()
{
pthread_cond_wait(&_cond,&_mutex);
}
bool IsEmpty()
{
return _task_queue.empty();
}
void HandlerTask(const std::string& name) // this
{
while (true)
{
LockQueue();
//如果队列为空(有任务)
while(IsEmpty()&&_isrunning) //线程没有任务,但是在工作,继续休眠
{
_sleep_thread_num++;
Sleep();
_sleep_thread_num--;
}
if(IsEmpty()&&!_isrunning) // 任务是空的,并且线程退出工作
{
std::cout<<name<<" quit..."<<std::endl;
UnlockQueue();
break;
}
// 队列不为空,有任务 或者 队列被唤醒
// 取任务
T t=_task_queue.front();
_task_queue.pop();
UnlockQueue();
// 此处任务已经不在任务队列中,任务已经被拿走,处理任务和临界资源是两码事
t(); // 处理任务,不能不用也不能在临界区中处理
std::cout<<name<<": "<<t.result()<<std::endl;
}
}
public:
ThreadPool(int thread_num=gdefaultnum)
:_thread_num(thread_num)
,_isrunning(false) //刚开始线程没有使用
,_sleep_thread_num(0)
{
pthread_mutex_init(&_mutex,nullptr);
pthread_cond_init(&_cond,nullptr);
}
void Init()
{
func_t func=std::bind(&ThreadPool::HandlerTask,this,std::placeholders::_1);
for(int i=0;i<_thread_num;i++)
{
std::string threadname="thread-"+std::to_string(i+1);
_threads.emplace_back(threadname,func);
}
}
void Start()
{
_isrunning=true;
for(auto& thread:_threads)
{
thread.Start();
}
}
void Stop()
{
LockQueue();
_isrunning=false;
WakeupAll();
UnlockQueue();
}
void Equeue(const T &in)
{
LockQueue();
if(_isrunning)
{
_task_queue.push(in);
// 如果当前有线程在等待,需要唤醒
if(_sleep_thread_num>0)
{
Wakeup();
}
}
UnlockQueue();
}
~ThreadPool()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond);
}
private:
int _thread_num;
std::vector<Thread> _threads; // 管理多个线程
std::queue<T> _task_queue; // 任务队列
bool _isrunning; //当前线程是否在工作
int _sleep_thread_num; //计数器:休眠的线程个数
pthread_mutex_t _mutex;
pthread_cond_t _cond;
}<