手写线程池(c++实现)

TaskQueue.h

#pragma once
#include <pthread.h>
#include <queue>

using callback = void(*)(void* arg);
template<typename T>
struct Task
{
	Task<T>() {
		function = nullptr;
		arg = nullptr;
	}
	Task<T>(callback f, void* arg) {
		function = f;
		this->arg = (T*)arg;
	}
	~Task<T>() {}
	callback function;
	T* arg;
};

template<typename T>
class TaskQueue
{
public:
	TaskQueue();
	~TaskQueue();
	void addTask(Task<T> task);//添加任务
	void addTask(callback cb, void* arg);
	Task<T> takeTask();//取任务
	inline size_t taskNumber()//获取当前任务的个数
	{
		return m_taskQ.size();
	}
private:
	std::queue<Task<T>> m_taskQ;
	pthread_mutex_t m_mutex;
};

TaskQueue.cpp

#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;
}

ThreadPool.h

#pragma once
#include "TaskQueue.h"
#include "TaskQueue.cpp"

template<typename T>
class ThreadPool
{
public:
	ThreadPool(int min, int max);
	~ThreadPool();
	// 给线程池添加任务
	void addTask(Task<T> task);
	// 获取线程池中工作的线程的个数
	int getBusyNum();
	// 获取线程池中活着的线程的个数
	int getAliveNum();
	//工作的线程(消费者线程)任务函数
	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;     //任务队列是不是空了
	bool shutdown;       //是不是要销毁线程池,销毁为true,不销毁为false
	static const int NUMBER = 2;
};

ThreadPool.cpp

#include "ThreadPool.h"
#include <iostream>
#include <string.h>
#include <string>
#include <pthread.h>
#include <unistd.h>
using namespace std;

template<typename T>
ThreadPool<T>::ThreadPool(int min, int max)
{
	do {
		taskQ = new TaskQueue<T>;
		if (taskQ == nullptr)
		{
			std::cout << "malloc taskQ fail..." << std::endl;
			break;
		}
		threadIDs = new pthread_t[max];
		if (threadIDs == nullptr)
		{
			std::cout << "malloc threadIDs fail..." << std::endl;
			break;
		}
		memset(threadIDs, 0, sizeof(pthread_t) * max);
		minNum = min;
		maxNum = max;
		busyNum = 0;
		liveNum = min;   // 和最小个数相等
		exitNum = 0;

		if (pthread_mutex_init(&mutexPool, NULL) != 0 ||
			pthread_cond_init(&notEmpty, NULL) != 0)
		{
			cout << "mutex or condition init fail...\n";
			break;
		}

		shutdown = false;

		//创建线程  参数:1 线程id地址 2 线程默认属性为空 3 管理者任务函数 4 给任务函数传递的参数
		pthread_create(&managerID, NULL, manager, this);
		for (int i = 0; i < min; i++) {
			pthread_create(&threadIDs[i], NULL, worker, this);
		}
		return;
	} while (0);

	//释放资源
	if (threadIDs) delete[] threadIDs;
	if (taskQ) delete taskQ;
}

template<typename 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<typename T>
void ThreadPool<T>::addTask(Task<T> task)
{
	if (shutdown)
	{
		return;
	}
	// 添加任务
	taskQ->addTask(task);
	pthread_cond_signal(&notEmpty);//唤醒消费者线程
}

template<typename T>
int ThreadPool<T>::getBusyNum()
{
	pthread_mutex_lock(&mutexPool);
	int busyNum = this->busyNum;
	pthread_mutex_unlock(&mutexPool);
	return busyNum;
}

template<typename T>
int ThreadPool<T>::getAliveNum()
{
	pthread_mutex_lock(&mutexPool);
	int aliveNum = this->liveNum;
	pthread_mutex_unlock(&mutexPool);
	return aliveNum;
}

template<typename T>
void* ThreadPool<T>::worker(void* arg)
{
	ThreadPool* pool = static_cast<ThreadPool*>(arg);
	while (1)
	{
		pthread_mutex_lock(&pool->mutexPool);
		// 当前任务队列是否为空
		while (pool->taskQ->taskNumber() == 0 && !pool->shutdown)
		{
			// 阻塞工作线程
			pthread_cond_wait(&pool->notEmpty, &pool->mutexPool);

			// 判断是不是要销毁线程
			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++;
		//开始工作
		cout<<"thread " << to_string(pthread_self()) << " start working...\n";
		//解锁
		pthread_mutex_unlock(&pool->mutexPool);
		task.function(task.arg);//(*task.function)(task.arg);
		delete task.arg;
		task.arg = nullptr;
		//结束工作
		cout<<"thread " << to_string(pthread_self()) <<" end working...\n";
		pthread_mutex_lock(&pool->mutexPool);
		pool->busyNum--;
		pthread_mutex_unlock(&pool->mutexPool);
	}
	return nullptr;
}

template<typename 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 = (int)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<typename T>
void ThreadPool<T>::threadExit()
{
	pthread_t tid = pthread_self();
	for (int i = 0; i < maxNum; i++)
	{
		if (threadIDs[i] == tid)
		{
			threadIDs[i] = 0;
			cout << "threadExit() called, " << to_string(tid) << " exiting...\n";
			break;
		}
	}
	pthread_exit(NULL);
}

test.cpp

#include <cstdio>
#include <stdio.h>
#include "ThreadPool.h"
#include "ThreadPool.cpp"
#include <unistd.h>
void taskFunc(void* arg)
{
	int num = *(int*)arg;
	printf("thread %ld is working, number = %d\n", pthread_self(), num);
	sleep(1);
}

int main()
{
	//创建线程池
	ThreadPool<int> pool(3, 10);
	for (int i = 0; i < 100; ++i)
	{
		int* num = new int(i+100);
		pool.addTask(Task<int>(taskFunc, num));
	}

	sleep(20);
	return 0;
}
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
手写一个简单的线程池,你可以按照以下步骤进行: 1. 创建一个任务队列,用于存储待执行的任务。 2. 创建一个固定数量的线程池,用于执行任务。 3. 每当有任务提交到线程池时,将任务添加到任务队列中。 4. 线程池中的每个线程会不断从任务队列中获取任务并执行。 5. 执行完一个任务后,线程继续从任务队列中获取下一个任务,并重复执行,直到任务队列为空。 下面是一个简单的 Java 代码示例: ```java import java.util.LinkedList; import java.util.Queue; public class ThreadPool { private final int poolSize; private final WorkerThread[] workerThreads; private final Queue<Runnable> taskQueue; public ThreadPool(int poolSize) { this.poolSize = poolSize; this.taskQueue = new LinkedList<>(); this.workerThreads = new WorkerThread[poolSize]; for (int i = 0; i < poolSize; i++) { workerThreads[i] = new WorkerThread(); workerThreads[i].start(); } } public void submit(Runnable task) { synchronized (taskQueue) { taskQueue.add(task); taskQueue.notify(); // 唤醒等待的线程 } } private class WorkerThread extends Thread { @Override public void run() { while (true) { Runnable task; synchronized (taskQueue) { while (taskQueue.isEmpty()) { try { taskQueue.wait(); // 等待新任务的到来 } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } } task = taskQueue.poll(); } try { task.run(); // 执行任务 } catch (RuntimeException e) { // 异常处理 } } } } // 使用示例 public static void main(String[] args) { ThreadPool threadPool = new ThreadPool(5); for (int i = 0; i < 10; i++) { final int index = i; threadPool.submit(() -> { System.out.println("Task " + index + " is running."); try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } System.out.println("Task " + index + " is complete."); }); } } } ``` 上述代码中,首先创建了一个任务队列 `taskQueue`,用于存储待执行的任务。然后创建了固定数量的线程池 `workerThreads`,每个线程会不断从任务队列中获取任务并执行。`ThreadPool` 类提供了 `submit` 方法,用于向线程池提交任务。 在 `main` 方法中,我们创建了一个大小为 5 的线程池,并向线程池提交了 10 个任务,每个任务会打印一段文字,并睡眠一秒钟模拟执行任务的耗时。你可以根据实际需求调整线程池的大小和任务的数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值