线程池C++面向对象封装

线程池

epoll不需要多线程的情况下可以实现多个socket交互;
使用了epoll前置服务器访问共享内存不会存在数据安全问题,但是因为单个线程单个进程操作必然会出现,多个socket同时操作,CPU随机轮片执行原则造成例如1000个客户端同时操作,单位之间只允许一个socket执行,起于999个要等待第一个socket完成以后才可以进行执行。
综上所述:开发服务器线程是必须的,线程解决的是多个socket读取到客户端的业务请求,防止数据到共享内存。
1、所谓线程池即存储多(N)个线程
2、服务器使用多少条线程是未知数,使用容器存储线程
3、线程池中分工作队列 a.忙碌队列 b.空闲队列 线程池一开始所有线程必须处于等待状态,等到任务数据唤醒线程。频繁开辟线程和销毁线程会调用内存,频繁使用内存,所以我们想着把线程执行完毕之后保留,用到下一个任务,达到不用重新创建线程和销毁线程。
4、任务队列
要实现线程池就是要实现队列,进行任务的移入和移出。
线程池是预先创建线程的一种技术,线程池在任务还没有到来之前,创建一定数量(N)的线程,放入空闲队列中,这些线程都是出于阻塞状态,不消耗CPU,但是占用较小的内存空间。当新任务到来时,缓冲区选择一个空闲线程,把任务传入此线程中运行,如果缓冲池已经没有空闲线程,则新建若干个线程,当系统比较空闲是,就将大部分线程都一直处于暂停状态,线程池自动销毁一大部分线程,回收系统资源。

服务器工作逻辑

在这里插入图片描述

线程池封装引入–如何进行线程池封装

线程池类
① 维护工作者线程队列(包括空闲和忙碌队列)
② 维护一个任务队列
③ 维护一个线程池调度器指针
线程池调度器(本身也是一个线程),负责线程调度,负责任务分配。
工作者线程类(线程池中的线程类的封装)
任务队列
任务接口(实际的业务逻辑都继承自该接口)

线程池的工作原理:

线程池类至少提供三个接口,初始化线程池,销毁线程池,添加任务接口
① 初始化线程池
开启线程池调度器线程
预先创建N个线程(由线程调度池器类负责创建工作者线程),放入空闲线程队列
指定最大的忙碌状态的线程数
② 销毁线程池
释放空闲队列中的线程与工作状态中的线程
释放调度器线程
③ 添加任务
添加一实际任务,但是并没有立刻运行该任务,只是放入任务队列,由线程池调度器从任务队列获取该任务,并从线程池中获得一个线程来运行该任务,这里实际上是一种生产者消费者模型。
线程池调度器包含创建空闲线程、销毁空闲线程接口

线程池调度器本身也是一个线程,主要负责任务调度与线程调度,其工作过程大致如下:
① 从任务队列获取任务,如果队列为空,阻塞等待新任务到来
② 队列不为空,取出该任务,从空闲线程队列取一线程,如果为空,判断工作者线程数是否达到上限,如果没有,则创建若个空闲线程,否则等待某一任务执行完毕,并且该任务对应的线程归还给线程池
③ 获得空闲工作者线程,将任务交给工作者线程来处理,工作者线程维护一任务指针,这里只要该指针指向任务,并且唤醒线程
④ 判断空闲工作者线程数是否超过最大工作者线程数,如果超过,销毁(空闲线程数-允许最大空闲线程数)个线程
A、任务接口是一个抽象类,只有一个虚函数run方法执行的是实际的业务逻辑
B、工作者线程维护一任务指针,工作者线程的任务主要是运行任务对象的run方法。
C、当线程池调度器调度一个工作者线程后,就唤醒工作者线程,并调用run方法来执行实际的业务逻辑,当run方法执行完毕,即业务逻辑处理结束,将工作者线程归还到空闲线程池队列,而不是销毁。这样线程池调度器下一次就有机会调度到该工作者线程。
代码:
先封装任务:
CTask.h:

#pragma once
class CTask
{
protected:
	char* Taskname;//任务名称
	void* Data;//任务数据
public:
	CTask(char* Taskname);
	~CTask();
	void setData(void* data);
	virtual int Run()=0;
};

CTask.cpp:

#include "CTask.h"
#include <string.h>
CTask::CTask(char* Taskname)
{
	strcpy(this->Taskname, Taskname);
	this->Data = NULL;
}

CTask::~CTask()
{

}

void CTask::setData(void* data)
{
	this->Data = data;
}

具体的业务:继承任务
CWorkTask.h:

#pragma once
#include "CTask.h"
class CWorkTask : public CTask
{
public:
	CWorkTask(char * Taskname);
	~CWorkTask();
	int Run();
};

CWorkTask.cpp:

#include "CWorkTask.h"
#include <iostream>
#include <stdio.h>
#include <unistd.h>
using namespace std;
CWorkTask::CWorkTask(char* Taskname):CTask(Taskname)
{

}

CWorkTask::~CWorkTask()
{
}
//子类实现具体的业务逻辑
int CWorkTask::Run()
{
    cout << (char*)this->Data << endl;
    sleep(10);
    return 0;
}

封装线程池:
Cthreadpoll.h:

#pragma once
#include "CTask.h"
#include <vector>
#include <iostream>
#include <pthread.h>
using namespace std;
class Cthreadpoll
{
public:
	//初始化线程池的时候,初始化线程池中的线程的数量
	Cthreadpoll(int threadNum);//线程池对象构造,传入线程数量
	~Cthreadpoll();
	int addTask(CTask *task);//增加新任务,将新任务添加到任务队列中
	int StopAll();//线程池停止
protected:
	static int moveToIdle(pthread_t tid);//线程任务执行结束后,将线程加入空闲队列
	static int moveTobusy(pthread_t tid);//如果任务,将线程加入到忙碌队列
	static void* ThreadFunction(void* threadData);
	int Create();//创建所有线程
private:
	int threadNum;//初始化线程池的时候,初始化线程池中的线程数量
	vector<CTask*> TaskList;//任务队列
	static vector<pthread_t> idleThread;//空闲队列
	static vector<pthread_t> busyThread;//忙碌队列
	static pthread_mutex_t ptheadmutex;//同步的锁对象
	static pthread_cond_t pthreadcond;//线程条件变量,等待/唤醒 状态切换

};

Cthreadpoll.cpp:

#include "Cthreadpoll.h"
//空闲队列
vector<pthread_t> Cthreadpoll::idleThread;
//忙碌队列
vector<pthread_t> Cthreadpoll::busyThread;
//同步的锁对象
pthread_mutex_t Cthreadpoll::ptheadmutex = PTHREAD_MUTEX_INITIALIZER;
//线程条件变量,等待/唤醒 状态切换
pthread_cond_t Cthreadpoll::pthreadcond = PTHREAD_COND_INITIALIZER;
/*
* 线程池对象构造,传入线程数量
*/
Cthreadpoll::Cthreadpoll(int threadNum)
{
    this->threadNum = threadNum;
    Create();
}

Cthreadpoll::~Cthreadpoll()
{
}
/*
* 线程任务执行结束后,将线程加入空闲队列
*/
int Cthreadpoll::moveToIdle(pthread_t tid)
{
    //遍历忙碌队列,找到该线程
    vector<pthread_t>::iterator busyIter = busyThread.begin();
    while (busyIter != busyThread.end())
    {
        if (*busyIter == tid)
        {
            break;
        }
        busyIter++;
    }
    //从忙碌队列中移除
    busyThread.erase(busyIter);
    //添加到空闲队列
    idleThread.push_back(tid);
    return 0;
}
/*
* 如果有任务,将线程加入到忙碌队列
*/
int Cthreadpoll::moveTobusy(pthread_t tid)
{
    //遍历空闲队列,找到该线程
    vector<pthread_t>::iterator idleIter = idleThread.begin();
    while (idleIter != idleThread.end())
    {
        if (*idleIter == tid)
        {
            break;
        }
        idleIter++;
    }
    //从空闲队列中移除
    idleThread.erase(idleIter);
    //添加到忙碌队列
    busyThread.push_back(tid);
    return 0;
}
/*
* 线程执行函数 参数为任务队列
*/
void* Cthreadpoll::ThreadFunction(void* threadData)
{
    pthread_t tid = pthread_self();//获取线程自己的id
    while (1)
    {
        pthread_mutex_lock(&ptheadmutex);
        //等待放在线程锁后面
        pthread_cond_wait(&pthreadcond,&ptheadmutex);
        cout << "线程 tid:" << tid <<"run"<<endl;
        //从任务队列中取出任务做事情,从任务队列中删除 进入忙碌队列
        vector<CTask*>* taskList = (vector<CTask*>*)threadData;
        vector<CTask*>::iterator iter = taskList->begin();
        while (iter != taskList->end())
        {
            moveTobusy(tid);
            break;
        }
        CTask* task = *iter;
        taskList->erase(iter);
        pthread_mutex_unlock(&ptheadmutex);
        cout << "空闲线程数量:" << Cthreadpoll::idleThread.size()<< endl;
        cout << "忙碌线程数:" << Cthreadpoll::busyThread.size() << endl;
        cout << "任务队列数:" << taskList->size() << endl;
        //执行具体的任务
        task->Run();
        cout << "任务执行完......" << endl;
        cout << "tid:" <<tid<<"空闲l"<< endl;
    }
    return nullptr;
}
/*
* 创建所有的线程 启动
*/
int Cthreadpoll::Create()
{
    //循环创建线程
    for (int i = 0; i < this->threadNum; i++)
    {
        pthread_t tid = 0;
        //创建形成,加入到标识符,将任务队列丢到线程中去
        pthread_create(&tid, NULL, ThreadFunction,&TaskList);
        //将线程加入到空闲队列
        idleThread.push_back(tid);
    }
    return 0;
}
/*
* 将新任务添加到任务队列中
*/
int Cthreadpoll::addTask(CTask* task)
{
    //添加任务都任务队列
    this->TaskList.push_back(task);
    //通知线程可以做事情了 唤醒满足条件的
    pthread_cond_signal(&pthreadcond);
    return 0;
}
/*
* 线程池停止
*/
int Cthreadpoll::StopAll()
{
    vector<pthread_t>::iterator iter = idleThread.begin();
    while( iter != idleThread.end() )
    {
        //通知系统,该线程可以结束
        pthread_cancel(*iter);
        //等待线程逻辑被执行完毕之后才结束
        pthread_join(*iter, NULL);
        iter++;

    }
    iter = busyThread.begin();
    while (iter != idleThread.end())
    {
        //通知系统,该线程可以结束
        pthread_cancel(*iter);
        //等待线程逻辑被执行完毕之后才结束
        pthread_join(*iter, NULL);
        iter++;
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逆龙泰氽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值