线程池封装

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;
}
相关推荐
蓝胖的四次元口袋13 小时前
服务器网络与系统基础-面试题
服务器·网络
Cx330❀14 小时前
【MySQL基础】一文吃透“表的约束”:从 Null/Default 到主外键的终极安全法则
linux·服务器·数据库·c++·mysql·安全
程序员JerrySUN14 小时前
Jetson 刷机深度解析:flash.sh vs l4t_initrd_flash.sh(含安全与磁盘加密对比)
linux·网络·arm开发·安全·系统安全
c2385614 小时前
第二篇:《测试指挥官:可视化单题自测框架(含 assert 实操)》
java·数据库·c++·算法·安全性测试
辞旧 lekkk15 小时前
【Redis初阶】常见数据类型
开发语言·数据库·c++·redis·学习·缓存·bootstrap
aduzhe15 小时前
关于lib文件格式(keil/unix)
服务器·unix
银河麒麟操作系统15 小时前
闸机高效稳跑,通勤提速升级!银河麒麟赋能北京轨交新基建
运维·服务器·安全·交通物流
六点_dn15 小时前
Linux学习笔记-printf命令
linux·运维·算法
蜡台15 小时前
Linux Python 安装使用
linux·运维·服务器
欧神附体12315 小时前
在虚拟机中添加网卡,修改网卡名并关闭SElinux
linux·服务器·网络