【转】一个简单的线程池(c++版)

本文介绍了一个基于Windows平台的线程池实现方法,通过创建和管理一组预先存在的线程来提高应用程序的并发性能。文章提供了详细的源代码,并解释了如何调整线程池规模、提交任务、以及如何优雅地关闭线程池。
#ifndef_ThreadPool_H_
#define_ThreadPool_H_
#pragmawarning(disable:4530)
#pragmawarning(disable:4786)
#include
<cassert>
#include
<vector>
#include
<queue>
#include
<windows.h>
classThreadJob//工作基类
{
public:
//供线程池调用的虚函数
virtualvoidDoJob(void*pPara)=0;
};
classThreadPool
{
public:
//dwNum线程池规模
ThreadPool(DWORDdwNum=4):_lThreadNum(0),_lRunningNum(0)
{
InitializeCriticalSection(
&_csThreadVector);
InitializeCriticalSection(
&_csWorkQueue);
_EventComplete
=CreateEvent(0,false,false,NULL);
_EventEnd
=CreateEvent(0,true,false,NULL);
_SemaphoreCall
=CreateSemaphore(0,0,0x7FFFFFFF,NULL);
_SemaphoreDel
=CreateSemaphore(0,0,0x7FFFFFFF,NULL);
assert(_SemaphoreCall
!=INVALID_HANDLE_VALUE);
assert(_EventComplete
!=INVALID_HANDLE_VALUE);
assert(_EventEnd
!=INVALID_HANDLE_VALUE);
assert(_SemaphoreDel
!=INVALID_HANDLE_VALUE);
AdjustSize(dwNum
<=0?4:dwNum);
}
~ThreadPool()
{
DeleteCriticalSection(
&_csWorkQueue);
CloseHandle(_EventEnd);
CloseHandle(_EventComplete);
CloseHandle(_SemaphoreCall);
CloseHandle(_SemaphoreDel);
vector
<ThreadItem*>::iteratoriter;
for(iter=_ThreadVector.begin();iter!=_ThreadVector.end();iter++)
{
if(*iter)
delete
*iter;
}
DeleteCriticalSection(
&_csThreadVector);
}
//调整线程池规模
intAdjustSize(intiNum)
{
if(iNum>0)
{
ThreadItem
*pNew;
EnterCriticalSection(
&_csThreadVector);
for(int_i=0;_i<iNum;_i++)
{
_ThreadVector.push_back(pNew
=newThreadItem(this));
assert(pNew);
pNew
->_Handle=CreateThread(NULL,0,DefaultJobProc,pNew,0,NULL);
assert(pNew
->_Handle);
}
LeaveCriticalSection(
&_csThreadVector);
}
else
{
iNum
*=-1;
ReleaseSemaphore(_SemaphoreDel,iNum
>_lThreadNum?_lThreadNum:iNum,NULL);
}
return(int)_lThreadNum;
}
//调用线程池
voidCall(void(*pFunc)(void*),void*pPara=NULL)
{
assert(pFunc);
EnterCriticalSection(
&_csWorkQueue);
_JobQueue.push(
newJobItem(pFunc,pPara));
LeaveCriticalSection(
&_csWorkQueue);
ReleaseSemaphore(_SemaphoreCall,
1,NULL);
}
//调用线程池
inlinevoidCall(ThreadJob*p,void*pPara=NULL)
{
Call(CallProc,
newCallProcPara(p,pPara));
}
//结束线程池,并同步等待
boolEndAndWait(DWORDdwWaitTime=INFINITE)
{
SetEvent(_EventEnd);
returnWaitForSingleObject(_EventComplete,dwWaitTime)==WAIT_OBJECT_0;
}
//结束线程池
inlinevoidEnd()
{
SetEvent(_EventEnd);
}
inlineDWORDSize()
{
return(DWORD)_lThreadNum;
}
inlineDWORDGetRunningSize()
{
return(DWORD)_lRunningNum;
}
boolIsRunning()
{
return_lRunningNum>0;
}
protected:
//工作线程
staticDWORDWINAPIDefaultJobProc(LPVOIDlpParameter=NULL)
{
ThreadItem
*pThread=static_cast<ThreadItem*>(lpParameter);
assert(pThread);
ThreadPool
*pThreadPoolObj=pThread->_pThis;
assert(pThreadPoolObj);
InterlockedIncrement(
&pThreadPoolObj->_lThreadNum);
HANDLEhWaitHandle[
3];
hWaitHandle[
0]=pThreadPoolObj->_SemaphoreCall;
hWaitHandle[
1]=pThreadPoolObj->_SemaphoreDel;
hWaitHandle[
2]=pThreadPoolObj->_EventEnd;
JobItem
*pJob;
boolfHasJob;
for(;;)
{
DWORDwr
=WaitForMultipleObjects(3,hWaitHandle,false,INFINITE);
//响应删除线程信号
if(wr==WAIT_OBJECT_0+1)
break;
//从队列里取得用户作业
EnterCriticalSection(&pThreadPoolObj->_csWorkQueue);
if(fHasJob=!pThreadPoolObj->_JobQueue.empty())
{
pJob
=pThreadPoolObj->_JobQueue.front();
pThreadPoolObj
->_JobQueue.pop();
assert(pJob);
}
LeaveCriticalSection(
&pThreadPoolObj->_csWorkQueue);
//受到结束线程信号确定是否结束线程(结束线程信号&&是否还有工作)
if(wr==WAIT_OBJECT_0+2&&!fHasJob)
break;
if(fHasJob&&pJob)
{
InterlockedIncrement(
&pThreadPoolObj->_lRunningNum);
pThread
->_dwLastBeginTime=GetTickCount();
pThread
->_dwCount++;
pThread
->_fIsRunning=true;
pJob
->_pFunc(pJob->_pPara);//运行用户作业
deletepJob;
pThread
->_fIsRunning=false;
InterlockedDecrement(
&pThreadPoolObj->_lRunningNum);
}
}
//删除自身结构
EnterCriticalSection(&pThreadPoolObj->_csThreadVector);
pThreadPoolObj
->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(),pThreadPoolObj->_ThreadVector.end(),pThread));
LeaveCriticalSection(
&pThreadPoolObj->_csThreadVector);
deletepThread;
InterlockedDecrement(
&pThreadPoolObj->_lThreadNum);
if(!pThreadPoolObj->_lThreadNum)//所有线程结束
SetEvent(pThreadPoolObj->_EventComplete);
return0;
}
//调用用户对象虚函数
staticvoidCallProc(void*pPara)
{
CallProcPara
*cp=static_cast<CallProcPara*>(pPara);
assert(cp);
if(cp)
{
cp
->_pObj->DoJob(cp->_pPara);
deletecp;
}
}
//用户对象结构
structCallProcPara
{
ThreadJob
*_pObj;//用户对象
void*_pPara;//用户参数
CallProcPara(ThreadJob*p,void*pPara):_pObj(p),_pPara(pPara){};
};
//用户函数结构
structJobItem
{
void(*_pFunc)(void*);//函数
void*_pPara;//参数
JobItem(void(*pFunc)(void*)=NULL,void*pPara=NULL):_pFunc(pFunc),_pPara(pPara){};
};
//线程池中的线程结构
structThreadItem
{
HANDLE_Handle;
//线程句柄
ThreadPool*_pThis;//线程池的指针
DWORD_dwLastBeginTime;//最后一次运行开始时间
DWORD_dwCount;//运行次数
bool_fIsRunning;
ThreadItem(ThreadPool
*pthis):_pThis(pthis),_Handle(NULL),_dwLastBeginTime(0),_dwCount(0),_fIsRunning(false){};
~ThreadItem()
{
if(_Handle)
{
CloseHandle(_Handle);
_Handle
=NULL;
}
}
};
std::queue
<JobItem*>_JobQueue;//工作队列
std::vector<ThreadItem*>_ThreadVector;//线程数据
CRITICAL_SECTION_csThreadVector,_csWorkQueue;//工作队列临界,线程数据临界
HANDLE_EventEnd,_EventComplete,_SemaphoreCall,_SemaphoreDel;//结束通知,完成事件,工作信号,删除线程信号
long_lThreadNum,_lRunningNum;//线程数,运行的线程数
};
#endif//_ThreadPool_H_

使用说明1

调用方法

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidthreadfunc(void*p)
{
YourClass
*yourObject=(YourClass*)p;
//
}
ThreadPooltp;
for(i=0;i<100;i++)
tp.Call(threadfunc);
ThreadPooltp(
20);//20为初始线程池规模
tp.Call(threadfunc,lpPara);

使用时注意几点:

1.ThreadJob 没什么用,直接写线程函数吧。

2. 线程函数(threadfunc)的入口参数void* 可以转成自定义的类型对象,这个对象可以记录下线程运行中的数据,并设置线程当前状态,以此与线程进行交互。

3. 线程池有一个EndAndWait函数,用于让线程池中所有计算正常结束。有时线程池中的一个线程可能要运行很长时间,怎么办?可以通过线程函数threadfunc的入口参数对象来处理,比如:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->classYourClass
{
intcmd;//cmd=1是上线程停止计算,正常退出。
};
threadfunc(
void*p){
YourClass
*yourObject=(YourClass*)p;
while(true){
//dosomecalculation
if(yourClass->cmd==1)
break;
}
}

在主线程中设置yourClass->cmd = 1,该线程就会自然结束。

使用说明2

ContractedBlock.gifExpandedBlockStart.gifCode
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->voidthreadfunc(void*p)
{
//
}
ThreadPooltp;
for(i=0;i<100;i++)
tp.Call(threadfunc);
ThreadPooltp(
20);//20为初始线程池规模
tp.Call(threadfunc,lpPara);
tp.AdjustSize(
50);//增加50
tp.AdjustSize(-30);//减少30

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->classMyThreadJob:publicThreadJob//线程对象从ThreadJob扩展
{
public:
virtualvoidDoJob(void*p)//自定义的虚函数
{
//.
}
};
MyThreadJobmt[
10];
ThreadPooltp;
for(i=0;i<100i++)
tp.Call(mt
+i);//tp.Call(mt+i,para);
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值