linux下c++版本线程池的实现

7 篇文章 0 订阅
本文档展示了用C++实现的任务队列和线程池的代码,包括任务队列的头文件和源文件,以及线程池的头文件和源文件。任务队列使用了STL的队列和互斥锁,线程池则包含工作线程和管理者线程,实现了动态调整线程数量以适应任务负载的功能。
摘要由CSDN通过智能技术生成

该版本的是来源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(&notEmpty, 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(&notEmpty);
	}
	// 释放堆内存
	if (taskQ)
	{
		delete taskQ;
	}
	if (threadIDs)
	{
		delete[] threadIDs;
	}

	
	pthread_mutex_destroy(&mutexPool);
	pthread_cond_destroy(&notEmpty);

}

template<class T>
void ThreadPool<T>::addTask(Task<T> task)
{
	
	// 判断线程池是否被关闭
	if (shutDown)
	{
		pthread_mutex_unlock(&mutexPool);
		return;
	}
	// 添加任务
	taskQ->addTask(task);

	pthread_cond_signal(&notEmpty);
	

}

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;




}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值