目录
一:了解线程池
二:线程池封装 案例
任务基类
#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递减
当所有的任务都执行完成了以后,忙碌线程会一个一个地转换为空闲线程。
直到所有的忙碌线程都转化为空闲线程。