该版本的是来源c语言版本的修改,只是对其进行了封装,这里不过得解释原理,大家可以看这篇文章
下面将直接上代码,同时这里需要主要的是使用的线程函数是linux自带的不是c++的自带线程函数,后续会使用c++提供一个线程池版本
目录
任务队列
头文件
#ifndef __TASKQUEUE__H
#define __TASKQUEUE__H
#include<queue>
#include<pthread.h>
using namespace std;
using callback = void(*)(void* arg);
template<typename T>
struct Task
{
Task<T>()
{
function = nullptr;
arg = nullptr;
}
Task<T>(callback f, void* arg)
{
this->arg = (T*)arg;
this->function = f;
}
callback function;
T* arg;
};
template<typename T>
class TaskQueue
{
public:
TaskQueue();
~TaskQueue();
//添加任务
void addTask(Task<T> task);
void addTask(callback f, void* arg);
// 取出任务
Task<T> takeTask();
// 获取当前任务个数
inline size_t taskNumber()
{
return m_taskQ.size();
}
//
private:
pthread_mutex_t m_mutex;
queue<Task<T>> m_taskQ;
};
#endif // !__TASKQUEUE__H
源文件
#include "TaskQueue.h"
template<typename T>
TaskQueue<T>::TaskQueue()
{
pthread_mutex_init(&m_mutex, NULL);
}
template<typename T>
TaskQueue<T>::~TaskQueue()
{
pthread_mutex_destroy(&m_mutex);
}
template<typename T>
void TaskQueue<T>::addTask(Task<T> task)
{
pthread_mutex_lock(&m_mutex);
m_taskQ.push(task);
pthread_mutex_unlock(&m_mutex);
}
template<typename T>
void TaskQueue<T>::addTask(callback f, void * arg)
{
pthread_mutex_lock(&m_mutex);
m_taskQ.push(Task<T>(f,arg));
pthread_mutex_unlock(&m_mutex);
}
template<typename T>
Task<T> TaskQueue<T>::takeTask()
{
Task<T> t;
pthread_mutex_lock(&m_mutex);
//判断任务队列是否为空
if (!m_taskQ.empty())
{
t = m_taskQ.front();//先取出
m_taskQ.pop();// 在弹出
}
pthread_mutex_unlock(&m_mutex);
return t;
}
线程池
线程池头文件
#ifndef __THREADPOOL__H
#define __THREADPOOL__H
#include"TaskQueue.h"
#include"TaskQueue.cpp"
#include<functional>
template<class T>
class ThreadPool
{
public:
// 创建线程池并初始化
ThreadPool(int min, int max);
// 销毁线程池
~ThreadPool();
// 给线程池添加任务
void addTask(Task<T> task);
// 获取线程池中工作的线程的个数
int getBusyNum();
// 获取线程池中活着的线程个数
int getAliveNum();
private:
/
// 工作的线程,消费者线程任务函数
static void* worker(void* arg);
// 管理者线程任务函数
static void* manager(void* arg);
// 单个线程退出
void threadExit();
private:
// 任务队列
TaskQueue<T>* taskQ; // 任务队列,数组,所以定义指针
pthread_t managerID; // 管理者线程ID
pthread_t *threadIDs; // 工作的线程ID
int minNum; // 最少线程数
int maxNum; // 最大线程数
int busyNum; // 在忙中的线程数
int liveNum; // 存活线程数
int exitNum; // 需要杀死的线程数
pthread_mutex_t mutexPool; // 锁整个线程池
pthread_cond_t notEmpty; // 任务队列是不是空了
// function<void*(void*)> workerFunc = worker;
static const int NUMBER = 2;
bool shutDown; // 是不是需要销毁线程池,销毁为1,不销毁为0
};
#endif // !__THREADPOOL__H
线程池源文件
#include "ThreadPool.h"
#include<iostream>
#include<string.h>
#include<string>
#include<unistd.h>
#include<pthread.h>
using namespace std;
template<class T>
ThreadPool<T>::ThreadPool(int min, int max):minNum(min), maxNum(max), liveNum(min),busyNum(0),exitNum(0), shutDown(false)
{
do
{
//实例化任务队列
taskQ = new TaskQueue<T>;
if (taskQ == nullptr)
{
cout << "new taskQ fail .... " << endl;
break;
}
threadIDs = new pthread_t[max]; // 根据最大的线程池设置进行创建空间
if (threadIDs == nullptr)
{
cout << "new theadIDs fail .... " << endl;
break;
}
memset(threadIDs, 0, sizeof(pthread_t)*max);
if (pthread_mutex_init(&mutexPool, NULL) != 0 ||
pthread_cond_init(¬Empty, NULL) != 0 )
{
cout<<"mutex or cond init error"<<endl;;
break;
}
// 创建线程
pthread_create(&managerID, NULL, manager, this);// 管理线程
for (int i = 0; i < min; ++i)
{
//printf("creating is %d\n", i);
pthread_create(&threadIDs[i], NULL, worker, this); // 工作线程
}
cout << "threadPoolCreate create sucess " << endl;
return;
} while (0);
//是否资源
if (threadIDs) delete[] threadIDs;
if (taskQ) delete taskQ;
}
template<class T>
ThreadPool<T>::~ThreadPool()
{
//关闭线程池
shutDown = true;
// 阻塞回收管理者线程
pthread_join(managerID, NULL);
// 唤醒阻塞的消费者线程
for (int i = 0; i < liveNum; i++)
{
pthread_cond_signal(¬Empty);
}
// 释放堆内存
if (taskQ)
{
delete taskQ;
}
if (threadIDs)
{
delete[] threadIDs;
}
pthread_mutex_destroy(&mutexPool);
pthread_cond_destroy(¬Empty);
}
template<class T>
void ThreadPool<T>::addTask(Task<T> task)
{
// 判断线程池是否被关闭
if (shutDown)
{
pthread_mutex_unlock(&mutexPool);
return;
}
// 添加任务
taskQ->addTask(task);
pthread_cond_signal(¬Empty);
}
template<class T>
int ThreadPool<T>::getBusyNum()
{
pthread_mutex_lock(&mutexPool);
int busyNum = this->busyNum;
pthread_mutex_unlock(&mutexPool);
return busyNum;
}
template<class T>
int ThreadPool<T>::getAliveNum()
{
pthread_mutex_lock(&mutexPool);
int aliveNum = this->liveNum;
pthread_mutex_unlock(&mutexPool);
return aliveNum;
}
template<class T>
void * ThreadPool<T>::worker(void * arg)
{
ThreadPool* pool = static_cast<ThreadPool*>(arg); //参数进行类型转换
while (true)
{
pthread_mutex_lock(&pool->mutexPool);
// 判断当前任务队列是否为空,且线程没有关闭
while (pool->taskQ->taskNumber() == 0 && !pool->shutDown)
{
// 需要阻塞线程,锁和条件变量进行绑定,后面通过条件变量对其进行唤醒
pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);
//判断是不是需要销毁线程,管理者线程会对exitNum进行初始化
if (pool->exitNum > 0)
{
pool->exitNum--;
if (pool->liveNum > pool->minNum)
{
pool->liveNum--;
pthread_mutex_unlock(&pool->mutexPool);
pool->threadExit();
}
}
}
// 如果有任务,则继续向下运行,开始消费任务了
// 判断线程池是否关闭了
if (pool->shutDown)
{
pthread_mutex_unlock(&pool->mutexPool);
pool->threadExit();
}
// 从任务队列取出任务
Task<T> task = pool->taskQ->takeTask();
// 任务队列应该设计成环形的队列,只需要确定头部和尾部即可,添加任务进行覆盖即可
// 移动头结点
// 解锁
pool->busyNum++;
pthread_mutex_unlock(&pool->mutexPool);
// 当前子线程开始工作了,因此忙的状态需要标定
cout << "thread " << to_string(pthread_self()) << " start working... " << endl;
// 开始工作
task.function(task.arg);
delete task.arg;
task.arg = nullptr;
// 当前子线程完成工作,因此把忙的状态取消
cout << "thread " << to_string(pthread_self()) << " end working... " << endl;
pthread_mutex_lock(&pool->mutexPool);
pool->busyNum--;
pthread_mutex_unlock(&pool->mutexPool);
}
return nullptr;
}
template<class T>
void * ThreadPool<T>::manager(void * arg)
{
ThreadPool* pool = static_cast<ThreadPool*>(arg);//参数进行类型转换
while (!pool->shutDown)
{
// 每隔3s检测一次
sleep(3);
//取出线程池中任务的数量和当前线程的数量
pthread_mutex_lock(&pool->mutexPool);
int queueSize = pool->taskQ->taskNumber();
int liveNum = pool->liveNum;
int busyNum = pool->busyNum;
pthread_mutex_unlock(&pool->mutexPool);
// 添加线程,需要制定一个添加的规则,可以根据实际情况进行设计即可
// 任务的个数>存活的线程个数 && 存活的线程个数< 最大线程数
if (queueSize > liveNum && liveNum < pool->maxNum)
{
pthread_mutex_lock(&pool->mutexPool);
int counter = 0;
for (int i = 0; i < pool->maxNum && counter < NUMBER && pool->liveNum < pool->maxNum; ++i)
{
if (pool->threadIDs[i] == 0)
{
pthread_create(&pool->threadIDs[i], NULL, worker, pool);
counter++;
pool->liveNum++;
}
}
pthread_mutex_unlock(&pool->mutexPool);
}
// 销毁线程
// 忙的线程*2 < 存活的线程数 && 存活的线程数>最小线程数
if (busyNum * 2 < liveNum && liveNum > pool->minNum)
{
pthread_mutex_lock(&pool->mutexPool);
pool->exitNum = NUMBER;
pthread_mutex_unlock(&pool->mutexPool);
// 让空闲的工作线程自杀
for (int i = 0; i < NUMBER; i++)
{
pthread_cond_signal(&pool->notEmpty);
}
}
}
return nullptr;
}
template<class T>
void ThreadPool<T>::threadExit()
{
pthread_t tid = pthread_self();
for (int i = 0; i < this->maxNum; i++)
{
if (this->threadIDs[i] == tid)
{
this->threadIDs[i] = 0;
cout << "threadExit() called " << to_string(tid) << " exiting ..." << endl;
break;
}
}
pthread_exit(NULL);
}
测试代码
#include <iostream>
#include<unistd.h>
#include"ThreadPool.h"
#include"ThreadPool.cpp"
using namespace std;
void taskFunc(void* arg)
{
int num = *(int*)arg;
cout << "thread " << to_string(pthread_self()) << " is working, number = " << num << endl;
sleep(1);
}
int main()
{
cout << " hello world ThreadPool_c++ " << endl;
//创建线程池
ThreadPool<int> pool(3, 10);
for (int i = 0; i < 100; i++)
{
int* num = new int(i+100);
//printf("*num = %d\n", *num);
pool.addTask(Task<int>(taskFunc,num));
}
sleep(30);
return 0;
}