首先介绍下线程池的作用,线程池属于一种多线程的使用模式,在运行时,生产者会将任务添加到任务队列中,而消费者会在创建线程后从此任务队列中获取任务来自动处理。这样避免了在短时间内创建和销毁线程的代价。线程池不仅能够内核的充分利用,还能防止过分调度。可用的线程数据取决于可用的并发处理器,处理内核,内存,网络sockets等数量。
线程池中的所有线程都有默认的堆栈大小和默认优先级运行。如果一个线程处于空闲态,例如等待某个事件的发生,那么线程池将会插入另一个线程来使所有的处理器保持繁忙。如果所有的线程始终保持繁忙,但队列中仍有未处理的任务,那么线程池将会在一段时间后创建额外的一个线程(但不会超过线程最大数量)来继续处理任务,如果超过了线程最大数量,那么线程要排队,等待处理任务的线程完成之后才能启动。
线程池的组成分为3个主要的部分:
manager线程:数量1个
(1)周期性检查任务队列的任务数以及处于繁忙状态的工作线程的数量;
(2)当任务过多时,可以根据策略适当增加一些新的工作线程;
(3)当任务过少时,可以根据策略释放销毁一些工作线程
worker线程:数量N个
(1)线程池创建维护一定数量的工作线程,这些工作线程会不断的读取任务队列,从队列里取出任务并处理;
(2)如果任务队列为空,工作线程将会被阻塞;
(3)如果阻塞之后有了新的任务,由生产者将阻塞解除,工作线程开始工作;
任务队列:由生产者推送,任务队列存储要处理的任务,工作线程来取并处理这些任务
(1)线程池提供API,将任务添加到任务队列,或者从任务队列中移除;
(2)已处理的任务将被移除;
(3)生产者调用线程池API往任务队列中添加任务。
1.任务队列
任务和任务队列声明:
#pragma once
#include<iostream>
#include<deque>
#include<thread>
#include<mutex>
#include<chrono>
using callback = void(*)(void* arg);
template<typename T>
struct Task{
Task():function(nullptr),arg(nullptr){}
Task(callback func,void* argument):function(func),arg(argument){}
callback function;
T* arg;
};
template<typename T>
class TaskQueue{
public:
TaskQueue() = default;
~TaskQueue() = default;
void pushTask(Task<T> task);
void pushTask(callback func,void* arg);
Task<T> takeTask();
inline int getTaskNum(){
return task_queue.size();
}
private:
std::mutex m_lock;
std::deque<Task> task_queue;
};
队列类的定义:
#include"Task.h"
template<typename T>
void TaskQueue<T>::pushTask(Task<T> task)
{
m_lock.lock();
task_queue.push_back(task);
m_lock.unlock();
}
template<typename T>
void TaskQueue<T>::pushTask(callback func,void* arg)
{
m_lock.lock();
task_queue.push_back(Task<T>(func,arg));
m_lock.unlock();
}
template<typename T>
Task<T> TaskQueue<T>::takeTask()
{
m_lock.lock();
Task<T> task = task_queue.front();
task_queue.pop_front();
m_lock.unlock();
return task;
}
2.线程池
类的声明:
#pragma once
#include"Task.h"
#include<condition_variable>
#include<vector>
#include<map>
template<typename T>
class threadPool{
public:
threadPool(int min,int max);
~threadPool();
void pushTask(Task<T> task);
int getBustNum();
int getLiveNum();
void exitThread();
private:
static void* manager(void*);
static void* worker(void*);
private:
TaskQueue<T>* m_task_queue;
std::thread* m_manager;
std::vector<std::thread*> m_workers;
int m_minNum;
int m_maxNum;
int m_liveNum;
int m_busyNum;
int m_destroyNum;
std::mutex m_pool_lock;
std::condition_variable m_cv;
bool m_isDestroy;
static const int STEP = 2;
};
类的定义:
#include"thread_pool.h"
#include<iostream>
#include<string>
#include<thread>
template<typename T>
threadPool<T>::threadPool(int min,int max):m_minNum(min),m_maxNum(max)
{
m_task_queue = new TaskQueue<T>;
if(!m_task_queue)
{
std::cout << "malloc task queue failed,exit..." << std::endl;
break;
}
m_busyNum = 0;
m_liveNum = min;
m_destroyNum = 0;
m_isDestroy = false;
m_manager = new std::thread(manager,std::ref(this));
for(int i = 0;i < min,i++)
{
m_workers.emplace_back(new std::thread(worker,std::ref(this)));
}
}
template<typename T>
threadPool<T>::~threadPool()
{
m_isDestroy = true;
m_manager->join();
m_cv.notify_all();//唤醒所有阻塞的线程,由线程自己做销毁
if(m_task_queue) delete m_task_queue;
}
template<typename T>
void threadPool<T>::pushTask(Task<T> task)
{
if(m_isDestroy)
return;
m_task_queue->pushTask(task);
m_cv.notify_one();
}
template<typename T>
int threadPool<T>::getBustNum()
{
m_pool_lock.lock();
int busyNum = m_busyNum;
m_pool_lock.unlock();
return busyNum;
}
template<typename T>
int threadPool<T>::getLiveNum()
{
m_pool_lock.lock();
int liveNum = m_liveNum;
m_pool_lock.unlock();
return liveNum;
}
template<typename T>
void* threadPool<T>::worker(void* arg)
{
threadPool* pool = static_cast<threadPool*>(arg);//传入类的this指针
while(true)
{
pool->m_pool_lock.lock();
while(pool->m_task_queue->getTaskNum() == 0 && !pool->m_isDestroy)
{
pool->m_cv.wait(pool->m_pool_lock);
if(pool->m_destroyNum > 0)
{
pool->m_destroyNum--;
pool->m_pool_lock.unlock();
pool->exitThread();
}
}
if(pool->m_isDestroy)
{
pool->m_pool_lock.unlock();
pool->exitThread();
}
Task<T> task = pool->m_task_queue->takeTask();
pool->m_busyNum++;
pool->m_pool_lock.unlock();
std::cout << "thread:" << std::this_thread::get_id() << " is running" << std::endl;
task.function(task.arg);
delete task.arg;
task.arg = nullptr;
std::cout << "thread:" << std::this_thread::get_id() << " finished work" << std::endl;
pool->m_pool_lock.lock();
pool->m_busyNum--;
pool->m_pool_lock.unlock();
}
return nullptr;
}
template<typename T>
void* threadPool<T>::manager(void* arg)
{
threadPool* pool = static_cast<threadPool*>(arg);//传入类的this指针
while(!pool->m_isDestroy)
{
sleep(5);
pool->m_pool_lock.lock();
int taskNum = pool->m_task_queue.size();
int busuNUm = pool->getBustNum();
int liveNum = pool->getLiveNum();
pool->m_pool_lock.unlock();
if(taskNum >liveNum && liveNum < pool->m_maxNum)
{
pool->m_pool_lock.lock();
int cnt = 0;
for(int i = 0;i < pool->m_maxNum && cnt < STEP && pool->getLiveNum() < pool->m_maxNum;i++)
{
m_workers.emplace_back(new std::thread(worker,std::ref(pool)));
cnt++;
pool->m_liveNum++;
}
pool->m_pool_lock.unlock();
}
if(busuNUm*2 < liveNum && liveNum >pool->m_minNum)
{
pool->m_pool_lock.lock();
pool->m_destroyNum = STEP;
pool->m_pool_lock.unlock();
for(int i = 0 ;i < STEP;i++)
{
pool->m_cv.notify_one();
}
}
}
return nullptr;
}
template<typename T>
void threadPool<T>::exitThread()
{
std::thread::id tid = std::this_thread::get_id();
for(std::vector<std::thread*>::iterator it = m_workers.begin();it != m_workers.end();it++)
{
std::thread* pthread(nullptr);
if((*it)->get_id() == tid)
{
pthread = *it;
(*it)->join();
delete pthread;
break;
}
}
m_workers.erase(it);
}