【Linux网络编程】- 线程池封装

目录

一:了解线程池

二:线程池封装 案例

三:线程池封装--测试线程池工作原理


一:了解线程池

了解线程池 

二:线程池封装 案例

任务基类

#pragma once
#include<iostream>
#include<string.h>

using namespace std;
class CBaseTask
{
public:
	CBaseTask(char *data);
	virtual ~CBaseTask();
	char data[1024];
	virtual void working() = 0;
};

#include "CBaseTask.h"

CBaseTask::CBaseTask(char* data)
{
	bzero(this->data,sizeof(this->data));
	memcpy(this->data, data, sizeof(this->data));
}

CBaseTask::~CBaseTask()
{
	delete this->data;
}

任务子类--继承父类

#pragma once
#include<iostream>
#include<unistd.h>
#include "CBaseTask.h"

using namespace std;
class ChildTask :
    public CBaseTask
{
public:
    ChildTask(char* data);
    ~ChildTask();
    void working();

};

#include "ChildTask.h"

ChildTask::ChildTask(char* data):CBaseTask(data)
{

}

ChildTask::~ChildTask()
{
}

void ChildTask::working()
{
	cout << this->data << "正在执行....." << endl;
	sleep(3);
}

线程池封装

注意点 添加命令-pthread 添加在链接器中,否则编译不过去

#pragma once
#include<iostream>
#include<queue>
#include<list>
#include<pthread.h>
#include<algorithm>
#include"CBaseTask.h"

#define MIN_NUM 10

using namespace std;

class CThreadPool
{
public:
	CThreadPool(const int num = MIN_NUM);
	~CThreadPool();
	//判断任务队列是否为空
	bool QueueIsEmpty();
	//互斥量操作
	void Lock();
	void unLock();
	//条件变量操作
	void Wait();
	void Wakeup();
	static void* RunTime(void* pv);//线程的执行函数
	void pushTask(CBaseTask* task);//添加任务到任务队列
	CBaseTask* popTask();//从任务队列移除任务
	void MoveIdle(pthread_t id);//移动到空闲链表
	void MoveBusy(pthread_t id);//移动到忙碌链表
private:
	int threadMINNUM;//最小线程数量
	int threadMAXNUM;//最大线程数量
	queue<CBaseTask*>taskQueue;//任务队列
	list<pthread_t>busyList;//忙碌链表
	list<pthread_t>idleList;//空闲链表

	pthread_mutex_t mutex;//线程互斥量 作用:做锁
	pthread_cond_t cond;//线程条件变量 作用:让线程出现阻塞或唤醒

};

#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, 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::pushTask(CBaseTask* task)
{
    Lock();
    this->taskQueue.push(task);
    unLock();
    //任务添加成功 唤醒线程开始执行工作
    Wakeup();
}

//从任务列表里取出任务
CBaseTask* CThreadPool::popTask()
{
    //任务列表中取出任务
    CBaseTask*  ptask = this->taskQueue.front();
    //任务列表中删除任务
    this->taskQueue.pop();
    //传出任务指针
    return ptask;
}

//线程变空闲 从忙碌到空闲
void CThreadPool::MoveIdle(pthread_t id)
{
    list<pthread_t>::iterator iter;
    iter = find(this->busyList.begin(), this->busyList.end(), id);
    if (iter != this->busyList.end())
    {
        //从忙碌删除
        this->busyList.erase(iter);
        //添加到空闲
        this->idleList.push_back(*iter);

    }
}

//线程变忙碌 从空闲到忙碌
void CThreadPool::MoveBusy(pthread_t id)
{
    list<pthread_t>::iterator iter;
    iter = find(this->idleList.begin(), this->idleList.end(),id);
    if (iter != this->idleList.end())
    {
        //从空闲删除
        this->idleList.erase(iter);
        //添加到忙碌
        this->busyList.push_back(*iter);

    }
}

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->MoveBusy(id);
        //取出任务
        CBaseTask* task = argThis->popTask();
        argThis->unLock();
        //任务工作
        task->working();

        argThis->Lock();
        argThis->MoveIdle(id);
        argThis->unLock();

        cout << "工作执行后 任务数: " << argThis->taskQueue.size() << endl;
        cout << "工作执行后 busy: " << argThis->busyList.size() << endl;
        cout << "工作执行后 idle: " << argThis->idleList.size() << endl;

        cout << "---------------------------------------------------------" << endl;

    }
    return nullptr;
}

主函数测试

#include<iostream>
#include"CThreadPool.h"
#include"ChildTask.h"
using namespace std;

int main()
{
	CThreadPool* pool = new CThreadPool(10);
	for (int i = 0; i < 10; i++)
	{
		char buf[40] = { 0 };
		sprintf(buf , " %s%d ", "任务", i);
		CBaseTask* task = new ChildTask(buf);
		pool->pushTask(task);
	}
	while (1){}
	return 0;
}

三:线程池封装--测试线程池工作原理

可以看出 设置任务业务10个,一开始空闲线程10 忙碌线程0 但是后面随着任务一个接一个地执行下去,忙碌线程+1递增 空闲线程-1递减

当所有的任务都执行完成了以后,忙碌线程会一个一个地转换为空闲线程。 

直到所有的忙碌线程都转化为空闲线程。 

猜你喜欢

转载自blog.csdn.net/m0_56051805/article/details/125952345
今日推荐