线程池封装

CThreadPool.h

cpp 复制代码
#pragma once

#include <pthread.h>
#include <list>
#include <queue>
#include <iostream>
#include <algorithm>

#include "CBaseTask.h"

#define MIN_THREAD_NUM 10

using namespace std;

class CThreadPool
{
public:
	CThreadPool(const int num = MIN_THREAD_NUM);
	~CThreadPool();

	// 添加任务
	void pushTask(CBaseTask* task);
	// 取出任务
	CBaseTask* popTask();

	// 从忙碌链表中删除添加到空闲链表
	void moveToIdle(pthread_t id);
	// 从空闲链表中删除添加到忙碌链表
	void moveToBusy(pthread_t id);

	// 判断任务队列是否为空
	bool queueIsEmpty();

	// 操作互斥量
	void lock();
	void unlock();

	//操作条件变量
	void wait(); // 阻塞线程
	void wakeup(); // 唤醒线程

	static void* pthread_function(void* arg);

private:
	int threadMinNum; // 线程数量最小值
	int threadMaxNum; // 线程数量最大值

	// 公共数据
	queue<CBaseTask*>taskQueue; // 任务队列
	list<pthread_t>idleList; // 空闲线程链表
	list<pthread_t>busyList; // 忙碌线程链表

	pthread_mutex_t mutex; // 互斥量
	pthread_cond_t cond; // 线程条件变量 控制 阻塞/唤醒
};

CThreadPool.cpp

cpp 复制代码
#include "CThreadPool.h"

CThreadPool::CThreadPool(const int num)
{
	this->threadMinNum = num;
	// 互斥量初始化
	pthread_mutex_init(&(this->mutex), NULL);
	// 条件变量初始化
	pthread_cond_init(&(this->cond), NULL);

	for (int i = 0; i < this->threadMinNum; i++)
	{
		pthread_t id;
		pthread_create(&id, NULL, this->pthread_function, this);
		
		// 将线程放入空闲列表
		this->idleList.push_back(id);
	}
}

CThreadPool::~CThreadPool()
{
}

void CThreadPool::pushTask(CBaseTask* task)
{
	this->taskQueue.push(task);
	this->wakeup();
}

CBaseTask* CThreadPool::popTask()
{
	// 取出队列中的任务
	CBaseTask* task = this->taskQueue.front();
	// 删除队列中的任务
	this->taskQueue.pop();
	return task;
}

void CThreadPool::moveToIdle(pthread_t id)
{
	list<pthread_t>::iterator itr;
	itr = find(this->busyList.begin(), this->busyList.end(), id);
	if (itr != this->busyList.end())
	{
		this->busyList.erase(itr);
		this->idleList.push_back(*(itr));
	}
}

void CThreadPool::moveToBusy(pthread_t id)
{
	list<pthread_t>::iterator itr;
	itr = find(this->idleList.begin(), this->idleList.end(), id);
	if (itr != this->idleList.end())
	{
		this->idleList.erase(itr);
		this->busyList.push_back(*(itr));
	}
}

bool CThreadPool::queueIsEmpty()
{
	return this->taskQueue.empty();
}

void CThreadPool::lock()
{
	pthread_mutex_lock(&(this->mutex));
}

void CThreadPool::unlock()
{
	pthread_mutex_unlock(&(this->mutex));
}

void CThreadPool::wait()
{
	pthread_cond_wait(&(this->cond), &(this->mutex));
}

void CThreadPool::wakeup()
{
	pthread_cond_signal(&(this->cond));
}

void* CThreadPool::pthread_function(void* arg)
{
	// 线程执行函数中 获取运行线程本身自己的id号
	pthread_t threadid = pthread_self();

	/*
	* 功能:确保主线程与当前执行的线程逻辑完全分离,当前线程执行结束,id会自动释放
	* 目的:为了声明这个线程不会阻塞主线程,pthread_detach不会种植线程的运行
	*/
	pthread_detach(threadid);

	CThreadPool* pool = (CThreadPool*)arg;

	while (1)
	{
		pool->lock(); // 其余线程都无法执行lock
		while (pool->queueIsEmpty())
		{
			pool->wait(); // 阻塞1个线程
		}

		cout << "线程工作前 任务数:" << pool->taskQueue.size() << endl;
		cout << "线程工作前 忙碌线程数:" << pool->busyList.size() << endl;
		cout << "线程工作前 空闲线程数:" << pool->idleList.size() << endl;

		if (pool->busyList.size() == pool->threadMinNum && pool->busyList.size() + pool->idleList.size() < pool->threadMaxNum)
		{
			pthread_t id;
			pthread_create(&id, NULL, pool->pthread_function, pool);

			// 将线程放入空闲列表
			pool->idleList.push_back(id);
		}

		pool->moveToBusy(threadid);
		
		CBaseTask* task = pool->popTask();
		pool->unlock();

		// 任务开始工作
		task->work();

		pool->lock();
		pool->moveToIdle(threadid);
		pool->unlock();

		cout << "线程工作后 任务数:" << pool->taskQueue.size() << endl;
		cout << "线程工作后 忙碌线程数:" << pool->busyList.size() << endl;
		cout << "线程工作后 空闲线程数:" << pool->idleList.size() << endl;
		cout << "------------------------------------------------------" << endl;
	}

	return nullptr;
}

main.cpp

cpp 复制代码
#include <iostream>

#include"CThreadPool.h"
#include "CBaseTask.h"
#include "CChildTask.h"

using namespace std;

int main()
{
	CThreadPool* pool = new CThreadPool();

	for (int i = 1; i <= 30; i++)
	{
		char buf[40] = { 0 };
		sprintf(buf, "任务%d", i);

		// 创建任务
		CBaseTask* task = new CChildTask(buf);
		// 添加任务进入线程池
		pool->pushTask(task);

		sleep(1);
	}

	while (1) {};

	return 0;
}
相关推荐
chlk12324 分钟前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑1 小时前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件1 小时前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
不想写代码的星星2 小时前
虚函数表:C++ 多态背后的那个男人
c++
深紫色的三北六号11 小时前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash15 小时前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
追逐时光者17 小时前
精选 5 款基于 .NET 开源的 Visual Studio 实用插件
visual studio
哈基咪怎么可能是AI1 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行2 天前
Linux和window共享文件夹
linux
端平入洛2 天前
delete又未完全delete
c++