线程池

来源:互联网 发布:中学生当街打母 知乎 编辑:程序博客网 时间:2024/04/28 06:05
最近脑袋有点犯贰。最近的工作总是涉及多线程,但网上的代码通用性不强。虽然windows已经内置了线程池,但是只能是VS2003以上的才能用,于是心一横就自己动手写了个线程池。
        该线程池可以在CONSOLE程序和GUI程序中都可用,如果想添加或者修改什么功能,可在源代码基础上进行。
        该线程池的包含了线程池和监视线程两个部分。线程池负责生成线程并响应外部的请求,监视线程负责监听外部线程请求,并从线程池获取可用的线程并执行。外部请求的工作函数必须符合unsigned workFunc(void* pvParam)形式,至于函数名可随意指定。工作函数可以是相同的函数也可以是不同的功能函数,这里就实现了功能定制。
        使用线程池之前,首先初始化线程池并指定线程池的容量大小,指定的容量大小不能大于线程池的最大容量。线程池默认容量大小为10,为了达到最好的性能和效率,建议使用者将线程池的容量设定为计算机CPU个数的2倍(这是一条经验规则)。
        初始化完成后可以向线程池添加工作函数,请遵循工作函数的原型规则。此时监视线程会向线程池请求一个可用的线程,如果线程请求已满,监视线程会循环检查可用的线程,如果得到一个可用的线程,将执行该工作函数。
        该线程池已经过本人的详细测试,如果还出现了问题请回复或者自行解决。

下面贴出线程池源代码和一个使用用例。

线程池头文件:

// CThreadPool.h: interface for the CThreadPool class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_)#define AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <afx.h>#include <process.h>typedef unsigned (/*__stdcall*/ *PWORKPROC)(void* pvParam);typedef struct _Thread{PWORKPROCpWorkFunc;void*pvParam;}Thread;typedef struct _threadInfo{BOOLbValid;UINTuiParamLen;UINTuiThreadId;UINTuiThreadIndex;Threadthread;HANDLE  hThread;HANDLE  hEvent;}ThreadInfo;#define MAX_CAPACITY 20//class CThreadPool  {public:CThreadPool();CThreadPool(UINT uiMaxCapacity);void IncreaseThreadCount();int  GetRequestCount();void DescendThreadCount();void ResetThreadInfo(UINT uiIndex);UINT GetValidThread(void);UINT GetMaxCapacity(void);UINT GetCurrentCount();void AddWorkItem(PWORKPROC workFunc, void* pvParam);UINT GetCapacity(void);int  InitThreadPool(UINT uiCapacity=8);virtual void DisplayAllThreadInfo(void);Thread* GetThreads();ThreadInfo* GetThreadInfo();static CThreadPool* GetCurrentPool(void);virtual ~CThreadPool();private:static CThreadPool* m_poCurrentPool;ThreadInfo* m_pThreadInfo;int  m_iReqCount;UINT m_uiCurrentCount;UINT m_uiMaxCapacity;UINT m_uiPoolCapacity;Thread* m_pThreads;};#endif // !defined(AFX_CTHREADPOOL_H__8015A6DC_2CCD_4436_AD0F_4F5178B69DA4__INCLUDED_)


线程池源文件:

// CThreadPool.cpp: implementation of the CThreadPool class.////////////////////////////////////////////////////////////////////////#include "CThreadPool.h"CThreadPool* CThreadPool::m_poCurrentPool=NULL;unsigned __stdcall ThreadProc(void* pvParam);unsigned __stdcall ListenThread(void* pvParam);HANDLE hListenThread=NULL;//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////CThreadPool::CThreadPool(){m_uiMaxCapacity=MAX_CAPACITY;m_poCurrentPool=this;}CThreadPool::CThreadPool(UINT uiMaxCapacity){m_uiMaxCapacity=uiMaxCapacity;m_poCurrentPool=this;}CThreadPool::~CThreadPool(){if (m_pThreadInfo!=NULL){delete (m_pThreadInfo);m_pThreadInfo=NULL;}if (m_pThreads!=NULL){delete (m_pThreads);m_pThreads=NULL;}for (UINT loop=0;loop<m_uiPoolCapacity;loop++){CloseHandle(m_pThreadInfo[loop].hThread);CloseHandle(m_pThreadInfo[loop].hEvent);}CloseHandle(hListenThread);}int CThreadPool::InitThreadPool(UINT uiCapacity){HANDLE hThread=NULL;HANDLE hEvent=NULL;UINT   uiThreadId=0;UINT   loop=0;m_pThreadInfo=NULL;m_uiCurrentCount=0;m_iReqCount=0;if (uiCapacity>m_uiMaxCapacity){return -1;}m_uiPoolCapacity=uiCapacity;m_pThreadInfo=new ThreadInfo[uiCapacity];m_pThreads=new Thread[MAX_CAPACITY];for (;loop<MAX_CAPACITY;loop++){m_pThreads[loop].pvParam=NULL;m_pThreads[loop].pWorkFunc=NULL;}for (loop=0;loop<m_uiPoolCapacity;loop++){m_pThreadInfo[loop].bValid=TRUE;m_pThreadInfo[loop].thread.pWorkFunc=NULL;m_pThreadInfo[loop].thread.pvParam=NULL;m_pThreadInfo[loop].uiParamLen=0;//m_pThreadInfo[loop].uiThreadIndex=loop;m_pThreadInfo[loop].hThread=NULL;m_pThreadInfo[loop].hEvent=NULL;hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);if (hEvent==NULL){return -2;}m_pThreadInfo[loop].hEvent=hEvent;hThread=(HANDLE)_beginthreadex(NULL,0,ThreadProc,(void*)(&m_pThreadInfo[loop].uiThreadIndex),0,&uiThreadId);//if (hThread==NULL){return -3;}m_pThreadInfo[loop].uiThreadId=uiThreadId;m_pThreadInfo[loop].hThread=hThread;}hListenThread=(HANDLE)_beginthreadex(NULL,0,ListenThread,NULL,0,NULL);//if (hListenThread==NULL){return -4;}return 0;}unsigned __stdcall ThreadProc(void* pvParam){CThreadPool* threadPool=NULL;ThreadInfo*  threadInfo=NULL;PWORKPROC workProc=NULL;void*     workParam=NULL;UINTuiIndex=0;uiIndex=*(int*)pvParam;threadPool=CThreadPool::GetCurrentPool();threadInfo=threadPool->GetThreadInfo();while(TRUE){if (WaitForSingleObject(threadInfo[uiIndex].hEvent,INFINITE)!=WAIT_OBJECT_0){continue ;}workProc=NULL;workParam=NULL;//printf("Execute thread:index=%d\thandle=%p\n", uiIndex,threadInfo[uiIndex].hThread);//workProc=threadInfo[uiIndex].thread.pWorkFunc;workParam=threadInfo[uiIndex].thread.pvParam;if (workProc!=NULL){workProc(workParam);}threadPool->ResetThreadInfo(uiIndex);threadPool->DescendThreadCount();}return 0;}void CThreadPool::AddWorkItem(PWORKPROC workFunc, void *pvParam){m_pThreads[m_iReqCount%MAX_CAPACITY].pWorkFunc=workFunc;m_pThreads[m_iReqCount%MAX_CAPACITY].pvParam=pvParam;m_iReqCount++;}unsigned __stdcall ListenThread(void* pvParam){CThreadPool* threadPool=NULL;ThreadInfo*  threadInfo=NULL;Thread* threads=NULL;PWORKPROC workProc=NULL;void*     workParam=NULL;int     iReqCount=0;intuiIndex=0;threadPool=CThreadPool::GetCurrentPool();threadInfo=threadPool->GetThreadInfo();threads=threadPool->GetThreads();while(TRUE){while(iReqCount!=threadPool->GetRequestCount()){workProc=NULL;workParam=NULL;uiIndex=threadPool->GetValidThread();//线程池请求已满,此处循环等待可用的线程if (uiIndex<0){continue ;}//printf("Request thread index:%d\n", uiIndex);threadPool->IncreaseThreadCount();workProc=threads[iReqCount%MAX_CAPACITY].pWorkFunc;workParam=threads[iReqCount%MAX_CAPACITY].pvParam;threadInfo[uiIndex].bValid=FALSE;threadInfo[uiIndex].thread.pvParam=workParam;threadInfo[uiIndex].thread.pWorkFunc=workProc;threadInfo[uiIndex].uiParamLen=0;//SetEvent(threadInfo[uiIndex].hEvent);iReqCount++;}}return 0;}void CThreadPool::DisplayAllThreadInfo(){//printf("Display all information of thread.\n");for (UINT loop=0;loop<GetCapacity();loop++){//printf("\tIndex:%d\tHandle:%p\tThreadId:%d\n", m_pThreadInfo[loop].uiThreadIndex,m_pThreadInfo[loop].hThread,m_pThreadInfo[loop].uiThreadId);}//printf("\n");}void CThreadPool::ResetThreadInfo(UINT uiIndex){m_pThreadInfo[uiIndex].bValid=TRUE;m_pThreadInfo[uiIndex].uiParamLen=0;//m_pThreadInfo[uiIndex].thread.pvParam=NULL;m_pThreadInfo[uiIndex].thread.pWorkFunc=NULL;}UINT CThreadPool::GetValidThread(){for (UINT loop=0;loop<GetCapacity();loop++){if (m_pThreadInfo[loop].bValid==TRUE){return m_pThreadInfo[loop].uiThreadIndex;}}return -1;}UINT CThreadPool::GetCapacity(){return m_uiPoolCapacity;}CThreadPool* CThreadPool::GetCurrentPool(){return m_poCurrentPool;}UINT CThreadPool::GetCurrentCount(){return m_uiCurrentCount;}UINT CThreadPool::GetMaxCapacity(){return m_uiMaxCapacity;}ThreadInfo* CThreadPool::GetThreadInfo(){return m_pThreadInfo;}void CThreadPool::DescendThreadCount(){--m_uiCurrentCount;}int CThreadPool::GetRequestCount(){return m_iReqCount;}void CThreadPool::IncreaseThreadCount(){m_uiCurrentCount++;}Thread* CThreadPool::GetThreads(){return m_pThreads;}

一个使用用例:

#include "CThreadPool.h"unsigned Test(void* param){printf("TEST%s for multiple threads.\n", (char*)param);return 0;}int main(int argc, char* argv[]){CThreadPool pool;int iRet=0;iRet=pool.InitThreadPool(4);if (iRet<0){printf("Initial thread pool;iRet=%d\n",iRet);return EXIT_FAILURE;}pool.DisplayAllThreadInfo();pool.AddWorkItem(Test,"0");//Sleep(1000);pool.AddWorkItem(Test,"1");//Sleep(1000);pool.AddWorkItem(Test,"2");//Sleep(1000);pool.AddWorkItem(Test,"3");//Sleep(1000);pool.AddWorkItem(Test,"4");WaitMessage(); //此处不可少return EXIT_SUCCESS;}

原创粉丝点击