线程池封装

CThreadPool.h

#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

#include "CThreadPool.h"

CThreadPool::CThreadPool(const int num)
{
	this->threadMinNum = num;
	this->threadMaxNum = MAX_THREAD_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->lock();
	if (this->idleList.empty() && (this->busyList.size() + this->idleList.size()) < this->threadMaxNum)
	{
		pthread_t id;
		pthread_create(&id, NULL, this->pthread_function, this);

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

	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;

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

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

		pool->lock();
		pool->moveToIdle(threadid);
		if (pool->idleList.size() > pool->threadMinNum && (pool->busyList.size() + pool->idleList.size()) > pool->threadMinNum)
		{
			// 当前线程将退出,不再参与后续任务
			pool->unlock();
			pthread_exit(NULL);
		}
		pool->unlock();

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

	return nullptr;
}

main.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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值