线程池

最近脑袋有点犯贰。最近的工作总是涉及多线程,但网上的代码通用性不强。虽然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
{
	PWORKPROC	pWorkFunc;
	void*		pvParam;
}Thread;

typedef struct _threadInfo
{
	BOOL	bValid;
	UINT	uiParamLen;
	UINT	uiThreadId;
	UINT	uiThreadIndex;
	Thread	thread;
	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;
	UINT	uiIndex=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;
	int		uiIndex=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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值