先来了解一下线程池的场景 :
我们想创建多个线程 来执行任务 有的时候没有那么多的任务 有的线程就不需要去工作
就会浪费 我们通常让这样的线程休眠 等到需要她的时候在唤醒 当任务太多 线程不够的时候 我们还可以创建几个 相反 当线程太多 任务太少时 我们还可以杀死几个线程
达到对线程的动态分配(这一篇还未达到真正的动态分配空间) (下一篇会完善)
完整代码如下
定义线程池类和任务类:
#ifndef CMYTHREADPOOL_H
#define CMYTHREADPOOL_H
#include<windows.h>
#include<list>
#include<queue>
class Itask
{
public:
Itask()
{}
virtual ~Itask()
{}
virtual void RunItask()=0;
};
class cMyThreadPool
{
public:
cMyThreadPool();
~cMyThreadPool();
public:
//创建线程池
bool CreateThreadPool(long Min,long Max,long MaxItask);
//销毁线程池
void DestroyThreadPool();
//取出任务
bool Push(Itask*pItask);
//线程函数
static DWORD WINAPI ThreadProc(LPVOID lpvoid);
private:
//线程链表
std::list<HANDLE> m_myhandlelist;
//线程池销毁标记
bool bFlag;
//信号量
HANDLE m_hSemaphore;
//任务队列
std::queue<Itask*> m_qitklist;
//创建的线程数
long m_lCreateThreadNum;
//最大线程数
long m_lMaxThreadNum;
//运行的线程数
long m_lRunThreadNum;
//当前任务数量
long m_lCurrentItaskNum;
//最大任务数量
long m_lMaxItaskNum;
//互斥量
HANDLE m_lMutex;
};
#endif // CMYTHREADPOOL_H
对
#include "cmythreadpool.h"
cMyThreadPool::cMyThreadPool()
{
bFlag=true;
m_hSemaphore=NULL;
m_lCreateThreadNum=NULL;
m_lMaxThreadNum=NULL;
m_lRunThreadNum=NULL;
m_lCurrentItaskNum=NULL;
m_lMaxItaskNum=NULL;
m_lMutex=CreateMutex(0,0,0);
}
cMyThreadPool::~cMyThreadPool()
{
}
bool cMyThreadPool::CreateThreadPool(long Min,long Max,long MaxItask)
{
HANDLE hand;
if(Min<=0||Max<Min)
return false;
m_hSemaphore=CreateSemaphoreW(0,//安全属性
0,//初始化信号量总数
MaxItask,//最大信号量总数
0//名字
);
//添加Min个线程到线程池中
for(long i=0;i<Min;i++)
{
hand=CreateThread(0,0,&ThreadProc,this,0,0);
if(hand)
{
m_myhandlelist.push_back(hand);
}
}
//当前线程数为Min个
m_lCreateThreadNum=Min;
//最大线程数为我们传进来的Max个
m_lMaxThreadNum=Max;
m_lMaxItaskNum= MaxItask;
return true;
}
void cMyThreadPool::DestroyThreadPool()
{
//销毁线程池
bFlag=false;
//遍历线程链表 逐个结束进程
auto ite=m_myhandlelist.begin();
while(ite!=m_myhandlelist.end())
{
if(WAIT_TIMEOUT== WaitForSingleObject(*ite,100))
//线程未正常 结束 杀死
TerminateThread(*ite,-1);
//正常结束 关闭句柄
CloseHandle(*ite);
*ite=NULL;
ite++;
}
//清空线程列表
m_myhandlelist.clear();
//关闭信号量
if(m_hSemaphore)
{
CloseHandle(m_hSemaphore);
m_hSemaphore=NULL;
}
//关闭互斥量
if(m_lMutex)
{
CloseHandle(m_lMutex);
m_lMutex=NULL;
}
// 任务执行完 回收任务的空间
Itask *pita=NULL;
while(m_qitklist.empty())
{
pita=m_qitklist.front();
m_qitklist.pop();
delete pita;
pita=NULL;
}
}
bool cMyThreadPool::Push(Itask*pItask)
{
//任务的参数校验
if(pItask==NULL)
return false;
//将任务放入任务队列
if(m_lCreateThreadNum==m_lMaxItaskNum)
{
Sleep(10);
}
//c++队列不允许同时pop和push 加个锁
WaitForSingleObject(m_lMutex,INFINITE);
m_qitklist.push(pItask);
ReleaseMutex(m_lMutex);
m_lCurrentItaskNum++;
//1.如果现在所有的线程都在工作 并且线程的数量没有达到最大值
//添加一个线程
if(m_lCreateThreadNum==m_lRunThreadNum&&
m_lCreateThreadNum <m_lMaxThreadNum)
{
HANDLE hand=CreateThread(0,0,&ThreadProc,this,0,0);
if(hand)
{
m_myhandlelist.push_back(hand);
}
m_lCreateThreadNum++;
}
//2.有空闲线程
//ReleaseSemaphore(m_hSemaphore,1,NULL);
//3.线程都在工作 并且线程数量达到最大值
//ReleaseSemaphore(m_hSemaphore,1,NULL);
//三种情况都有 ReleaseSemaphore(m_hSemaphore,1,NULL);
//拿出来 后两种情况被简化了
ReleaseSemaphore(m_hSemaphore,1,NULL);
return true;
}
DWORD WINAPI cMyThreadPool::ThreadProc(LPVOID lpvoid)
{
cMyThreadPool*pthis=(cMyThreadPool*)lpvoid;
Itask*pita=NULL;
while(1)
{
//等信号
WaitForSingleObject(pthis->m_hSemaphore,INFINITE);
//从队列中取出 任务
//当前正在执行的任务+1
//这里不允许多个线程同时执行++ 采用原子操作
//pthis->m_lRunThreadNum++;
InterlockedIncrement(&pthis->m_lRunThreadNum);
//任务列表不为空 执行任务
if(!pthis->m_qitklist.empty())
{
WaitForSingleObject(pthis->m_lMutex,INFINITE);
if(pthis->m_qitklist.empty())
{
ReleaseMutex(pthis->m_lMutex);
continue;
}
pita=pthis->m_qitklist.front();
//此任务出队
pthis->m_qitklist.pop();
ReleaseMutex(pthis->m_lMutex);
//执行任务
pita->RunItask();
//pthis->m_lCurrentItaskNum--;
InterlockedDecrement(&pthis->m_lRunThreadNum);
//回收空间
delete pita;
pita=NULL;
}
//pthis->m_lRunThreadNum--;
InterlockedDecrement(&pthis->m_lRunThreadNum);
}
return 0;
}
主函数
#include <QCoreApplication>
#include"cmythreadpool.h"
#include<iostream>
using namespace std;
class Additask:public Itask
{
private:
int m_a;
int m_b;
public:
Additask(int a,int b)
{
m_a=a;
m_b=b;
}
~Additask()
{}
void RunItask()
{
cout<<m_a<<"+"<<m_b<<"="<<m_a+m_b<<endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cMyThreadPool mt;
//创建线程池
mt.CreateThreadPool(10,100,10000);
//添加100个任务
for(int i=0;i<10000;i++)
{
Itask*add1=new Additask(i,i+1);
//将任务投递到线程池中
mt.Push(add1);
//
//Sleep(10);
}
return a.exec();
}