Linux 线程池

1. 什么是线程池

        池是一组资源的集合,这组资源在服务器启动之初就完全被创建并初始化,这称为静态资源分配。当服务器进入正式运行阶段,即开始处理客户请求的时候,如果它需要相关的资源,就可以直接从池中获取,无需动态分配。很显然,直接从池中取得所需资源比动态分配资源的速度要快得多,因为分配系统资源的系统调用都是很耗时的。当服务器处理完一个客户连接后,可以把相关的资源放回池中,无需执行系统调用来释放资源。

2.  优点

         1. 线程池避免了在处理短时间任务时创建与销毁线程的代价。

         2. 线程池不仅能够保证内核充分利用,还能防止过分调度。

注意: 线程池中可用线程的数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

   1)需要大量的线程来完成任务,且完成任务的时间比较短。线程池的好处是避免了繁琐的创建和结束线程的时间,有效的利用了CPU资源。 比如WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大>但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
 2)对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
 3)接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

3. 应用场景

线程池常见的应用场景如下:

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。
  2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

4. 线程池的实践

三要素: 

1. 线程队列

        存放被创建的线程, 这些线程被分为两种状态这两种状态的线程使用两条链表存储

        1. 正在执行任务的线程 (忙碌)

        2. 等待分配任务的线程 (空闲)

2. 任务队列

        使用队列的方式存储添加进来的线程, 添加时会通知空闲队列取任务执行。

3. 控制器

一个线程互斥量以及一个线程条件变量(使用两个控制器达到线程进行控制 进行阻塞或则唤醒)

当任务队列中有一个任务时,在线程队列中还有空闲的线程则会唤醒一个线程去完成任务

5 . 线程池的流程

 

6. 实现代码

        第一创建一个线程要执行的任务基类, 不同任务创建派生类并继承该基类就可实现不同任务。

#pragma once
/********************************************
	文件: CBasetast.h
	作者: yida_li
	日期: 2022/07/23 11 : 15
	功能: 事件基类
*********************************************/

#include <string.h>

class CBasetast
{
public:
	CBasetast(char * tast);
	virtual ~CBasetast();
	virtual void workTast() = 0;
private:
	char buf[1024];

};

#include "CBasetast.h"

CBasetast::CBasetast(char* tast)
{
	memcpy(this->buf, tast, sizeof(this->buf));
}

CBasetast::~CBasetast()
{
	delete this->buf;
}



其次创建一个任务基类的派生类

#pragma once
/********************************************
	文件: WorkTast1.h
	作者: yida_li
	日期: 2022/07/23 11 : 32
	功能: 工作类 1
*********************************************/


#include <iostream>
#include <string.h>
#include <unistd.h>
#include "CBasetast.h"
using namespace std;
/********************************************
	文件: WorkTast1.h
	作者: yida_li
	日期: 2022/07/26 1 : 41
	功能: 任务派生类
*********************************************/
class WorkTast1 :
    public CBasetast
{
public:
    WorkTast1(char* tast);
    ~WorkTast1();
    void workTast();   //工作函数
private:
	char buf[1024];
};

#include "WorkTast1.h"

WorkTast1::WorkTast1(char* tast):CBasetast(tast)
{
	memcpy(this->buf, tast, sizeof(this->buf));
}

WorkTast1::~WorkTast1()
{
}

void WorkTast1::workTast()
{
	cout << " 正在执行任务中 。。。  " << this->buf << endl;
}

最后创建最重要的 线程的实现类

#pragma once

#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include "CBasetast.h"
using namespace std;

#define CREAT_MIN_NUM 10
#define CREAT_MAX_NUM 30

class CThreadPool
{
public:
	CThreadPool( const int creat_num = CREAT_MIN_NUM);
	~CThreadPool();

	//判断任务队列是否为空
	bool QueueIsEmpty();
	//互斥量操作
	void Lock(); 
	void unLock();
	//条件变量操作
	void wait();
	void wakeUp();


	static void* RunTime(void* pv);//线程执行函数
	void pushTask(CBasetast* task);//添加任务到任务队列
	CBasetast* popTask();//从任务队列移除任务
	void MoveToIdle(pthread_t id);//移动到空闲链表
	void MoveToBusy(pthread_t id);//移动到忙碌链表


private:
	int threadMinNum;//最小线程数量
	int threadMaxNum;//最大线程数量
	queue<CBasetast*>taskQueue;//任务队列
	list<pthread_t>busyList;//忙碌链表
	list<pthread_t>idleList;//空闲链表
	pthread_mutex_t mutex;//线程互斥量作用:做锁
	pthread_cond_t cond;//线程条件变量作用:让线程出现阻塞或唤醒

};

#include "CThreadPool.h"

//构造函数
CThreadPool::CThreadPool(const int creat_num)
{
	this->threadMinNum = creat_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, RunTime, this);
		this->idleList.push_back(id);
	}
}

CThreadPool::~CThreadPool()
{

}

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::RunTime(void* pv)
{
	//某线程在执行过程中先获取到自己的id,以便之后操作移动到空闲移动到忙碌的动作
	pthread_t id = pthread_self();
	//确保主线程与当前执行线程逻辑完全分离,当前执行线程执行结束后,id会自动释放
	//分离目的:为了声明这个线程不会阻塞主线程的逻辑,pthread_detach不会终止当前执行线程pthread_detach(id);
	CThreadPool* argThis = (CThreadPool*)pv; 
	while (true)
	{
		argThis->Lock();
		while (argThis->QueueIsEmpty()) {
			
			argThis->wait();
		}
		cout << "工作执行前任务数:" << argThis->taskQueue.size() << endl;
		cout << "工作执行前busy: " << argThis->busyList.size() << endl;
		cout << "工作执行前idle: " << argThis->idleList.size() << endl; 
		cout << "------------------这是执行任务前的---------------------------------------------------- - " << endl;
		argThis->MoveToBusy(id);
		//取任务
		CBasetast* task = argThis->popTask();
		argThis->unLock();
		//任务工作
		task->workTast();
		argThis->Lock();
		argThis->MoveToIdle(id);
		cout << endl;
		cout << "工作执行后任务数:" << argThis->taskQueue.size() << endl;
		cout << "工作执行后busy: " << argThis->busyList.size() << endl;
		cout << "工作执行后idle: " << argThis->idleList.size() << endl;
		cout <<  " ----------------------------以上是任务执行后的----------------------------------------- " << endl;
		argThis->unLock();
			
		
	}
		


	CThreadPool* pp = (CThreadPool*)pv;
	return pp;
	//return nullptr;
}


//添加任务进任务队列
void CThreadPool::pushTask(CBasetast* task)
{
	Lock(); //锁住
	this->taskQueue.push(task);
	unLock(); //解锁
	wakeUp();  // 任务成功添加进任务队列中,之后开始唤醒线程开始工作执行任务
}
//从任务列表中取出任务,并释放掉队头
CBasetast* CThreadPool::popTask()
{
	CBasetast* pp = this->taskQueue.front();   //取出任务队列头赋值给一个临时的任务类对象
	this->taskQueue.pop();  //取出任务后手动释放掉
	return pp;
}
//从忙碌链表到空闲空闲链表
void CThreadPool::MoveToIdle(pthread_t id)
{
	list<pthread_t>::iterator iterator1;
	iterator1 = find(this->busyList.begin(), this->busyList.end(), id);
	if (iterator1 != this->busyList.end())
	{
		this->busyList.erase(iterator1);  //取出空闲链表
		this->idleList.push_back(*iterator1);  //插入 iterator1 到忙碌链表
	}
	

}
//从空闲链表到忙碌链表
void CThreadPool::MoveToBusy(pthread_t id)
{
	list<pthread_t>::iterator iterator1;
	iterator1 = find(this->idleList.begin(), this->idleList.end(), id);
	if (iterator1 != this->idleList.end())
	{
		this->idleList.erase(iterator1);   //从忙碌队列中删除掉 iterator1
		this->busyList.push_back(*iterator1); // 插入iterator1 到空闲链表中
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值