线程池浅析及C++代码实现

(1)什么是线程池  线程池是一种多线程处理技术。线程池先创建好若干线程,并管理这些线程。当有新的任务到来时,将任务添加到一个已创建的空闲线程中执行。线程池所创建的线程优先级都是一样的,所以需要使用特定线程优先级的任务不宜使用线程池。  


(2)线程池的优点和应用  线程池统一管理线程的方式减少了频繁创建和销毁线程的系统调度开销,很大程度上提高了服务器处理并发任务的性能。  线程池适用于频繁的任务调度,如处理HTTP请求,任务多,并且任务周期小  


(3)C++代码实现

  #include "stdafx.h"

  #include "stdafx.h"

  #include <assert.h>

  #include <windows.h>

  #include <map>

  #include <iostream>

  using namespace std;

  class ITask

  {

     public:

       virtual void ProcessTask(void* pUser)=0;

  };

  //線程池

  class CThreadPool
  {
      public: 
           class ThreadInfo
  {

  public:

  	ThreadInfo() { m_hThread=0;m_bBusyWorking=false;}

  	ThreadInfo(HANDLEhandle, boolbBusy) { m_hThread=handle; m_bBusyWorking=bBusy; }

  	ThreadInfo(const ThreadInfo& info){ m_hThread=info.m_hThread; m_bBusyWorking=info.m_bBusyWorking;}

  	HANDLE m_hThread;

  	bool m_bBusyWorking;

  };

  typedef map<DWORD,ThreadInfo>ThreadInfoMap;

  typedef ThreadInfoMap::iterator Iterator_ThreadInfoMap;

  enum ThreadPoolStatus{ STATUS_BUSY, STATUS_IDLE,STATUS_NORMAL };

  public:

  CThreadPool()

  {

  	InitializeCriticalSection(&m_CS);

  }

  virtual ~CThreadPool()

  {

  	DeleteCriticalSection(&m_CS);

  }

  bool Start(unsigned short nStatic, unsigned short nMax)

  {

  	if(nMax<nStatic)

  	{

  		assert(0);

  		return false;

  	}

  	HANDLE hThread;

  	DWORD nThreadId;

  	m_nNumberOfStaticThreads=nStatic;

  	m_nNumberOfTotalThreads=nMax;

  	//lock the resource

  	EnterCriticalSection(&m_CS);

  	//create an IO port

  	m_hMgrIoPort = CreateIoCompletionPort((HANDLE)INVALID_HANDLE_VALUE,NULL, 0, 0);

  	hThread = CreateThread(

  	NULL, // SD

  	0, // initial stack size

  	(LPTHREAD_START_ROUTINE)ManagerProc, // threadfunction

  	(LPVOID)this, // thread argument

  	0, // creationoption

  	&nThreadId ); // thread identifier

  	m_hMgrThread = hThread;

  	//now we start these worker threads

  	m_hWorkerIoPort = CreateIoCompletionPort((HANDLE)INVALID_HANDLE_VALUE,NULL, 0, 0);

  	for(long n = 0; n < nStatic; n++)

  	{

  		hThread = CreateThread(

  		NULL, // SD

  		0, // initial stack size

  		(LPTHREAD_START_ROUTINE)WorkerProc, // threadfunction

  		(LPVOID)this, //thread argument

  		0, //creation option

  		&nThreadId );

  		m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(nThreadId,ThreadInfo(hThread, false)));

  	}

  	LeaveCriticalSection(&m_CS);

  	return true;

  	}

  	void Stop(bool bHash = false)

  	{

  	EnterCriticalSection(&m_CS);

  	::PostQueuedCompletionStatus(m_hMgrIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFF);

  	WaitForSingleObject(m_hMgrThread,INFINITE);

  	CloseHandle(m_hMgrThread);

  	CloseHandle(m_hMgrIoPort);

  	//shut down all the worker threads

  	UINT nCount=m_threadMap.size();

  	HANDLE* pThread= new HANDLE[nCount];

  	long n=0;

  	ThreadInfo info;

  	Iterator_ThreadInfoMap i=m_threadMap.begin();

  	while(i!=m_threadMap.end())

  	{

  	::PostQueuedCompletionStatus(m_hWorkerIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFF);

  	info=i->second;

  	pThread[n++]=info.m_hThread;

  	i++;

  	}

  	DWORD rc=WaitForMultipleObjects(nCount,pThread, TRUE,30000);//wait for 0.5 minutes, then start to killthreads

  	CloseHandle(m_hWorkerIoPort);

  	if(rc>=WAIT_OBJECT_0 && rc<WAIT_OBJECT_0+nCount)

  	{

  	for(unsigned int n=0;n<nCount;n++)

  	{

  	CloseHandle(pThread[n]);

  	}

  	}

  	else if(rc==WAIT_TIMEOUT&&bHash)

  	{

  		//some threadsnot terminated, we have to stop them.

  		DWORD exitCode;

  		for(unsigned int i=0; i<nCount; i++)

  		{

  			if (::GetExitCodeThread(pThread[i],&exitCode)==STILL_ACTIVE)

  			{

  				TerminateThread(pThread[i], 99);

  			}

  			CloseHandle(pThread[i]);

  		}

  	}

  	delete[] pThread;

  	LeaveCriticalSection(&m_CS);

  }

  void AddTask(void* pUser, ITask* pWorker)const

  {

  	::PostQueuedCompletionStatus(m_hWorkerIoPort, \

  	reinterpret_cast<DWORD>(pWorker), \

  	reinterpret_cast<DWORD>(pUser),\

  	NULL);

  }

  protected:

  	HANDLE GetMgrIoPort()const { return m_hMgrIoPort; }

  	UINT GetMgrWaitTime()const { return1000; }

  	HANDLE GetWorkerIoPort()const { return m_hWorkerIoPort; }

  private:

  static DWORD WINAPI WorkerProc(void* p)

  {

  	//convert the parameter to the server pointer.

  	CThreadPool* pServer=(CThreadPool*)p;

  	HANDLE IoPort = pServer->GetWorkerIoPort();

  	unsigned long pN1,pN2;

  	OVERLAPPED* pOverLapped;

  	DWORD threadId=::GetCurrentThreadId();

  	while(::GetQueuedCompletionStatus(IoPort, &pN1,&pN2,

  	&pOverLapped, INFINITE))

  	{

  		if(pOverLapped ==(OVERLAPPED*)0xFFFFFFFE)

  		{

  			pServer->RemoveThread(threadId);

  			break;

  		}

			else if(pOverLapped == (OVERLAPPED*)0xFFFFFFFF)

  		{

  			break;

  		}

  		else

  		{

  			pServer->SetStatus(threadId, true);

  			//retrieve the job description and agent pointer

  			ITask* pTask = reinterpret_cast<ITask*>(pN1);

  			void* pUser= reinterpret_cast<void*>(pN2);

  			pTask->ProcessTask(pUser);

  			pServer->SetStatus(threadId, false);

  		}

  	}

  	return 0;

  }

  static DWORD WINAPI ManagerProc(void* p)

  {

  	//convert the parameter to the server pointer.

  	CThreadPool* pServer=(CThreadPool*)p;

  	HANDLE IoPort = pServer->GetMgrIoPort();

  	unsigned long pN1,pN2;

  	OVERLAPPED* pOverLapped;

  	LABEL_MANAGER_PROCESSING:

  	while(::GetQueuedCompletionStatus(IoPort, &pN1,&pN2,

  	&pOverLapped, pServer->GetMgrWaitTime() ))

  	{

  		if(pOverLapped ==(OVERLAPPED*)0xFFFFFFFF)

  		{

  		return 0;

  	}

  	}

  	//time out processing

  	if (::GetLastError()==WAIT_TIMEOUT)

  	{

  	   //the manager will take a look at all the worker's status.The

  	   if (pServer->GetStatus()==STATUS_BUSY)

  	     pServer->AddThreads();

  	   if (pServer->GetStatus()==STATUS_IDLE)

  	     pServer->RemoveThreads();

  	   goto LABEL_MANAGER_PROCESSING;

  	}

  	return 0;

  }

  protected:

      //manager thread

      HANDLE m_hMgrThread;

      HANDLE m_hMgrIoPort;

  protected:

     //configuration parameters

     mutable unsigned short m_nNumberOfStaticThreads;

      mutable unsigned short m_nNumberOfTotalThreads;

  protected:

    //helper functions

  void CThreadPool::AddThreads()

  {

  	HANDLE hThread;

  	DWORD nThreadId;

  	unsigned int nCount=m_threadMap.size();

  	unsigned int nTotal=min(nCount+2, m_nNumberOfTotalThreads);

  	for(unsigned int i=0; i<nTotal-nCount; i++)

  	{

  		hThread = CreateThread(

  		NULL, // SD

  		0, // initial stack size

  		(LPTHREAD_START_ROUTINE)WorkerProc, // threadfunction

  		(LPVOID)this, //thread argument

  		0, //creation option

  		&nThreadId );

  		m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(nThreadId,ThreadInfo(hThread, false)));

  	}

  }

  void RemoveThreads()

  {

  	unsigned int nCount=m_threadMap.size();

  	unsigned int nTotal=max(nCount-2, m_nNumberOfStaticThreads);

  	for(unsigned int i=0; i<nCount-nTotal; i++)

  	{

  		::PostQueuedCompletionStatus(m_hWorkerIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFE);

  	}

  }

  ThreadPoolStatus GetStatus()

  {

  	int nTotal = m_threadMap.size();

  	ThreadInfo info;

  	int nCount=0;

  	Iterator_ThreadInfoMap i=m_threadMap.begin();

  	while(i!=m_threadMap.end())

  	{

  		info=i->second;

  		if (info.m_bBusyWorking==true)nCount++;

  		i++;

  	}

  	if ( nCount/(1.0*nTotal) > 0.8 )

  	return STATUS_BUSY;

  	if ( nCount/ (1.0*nTotal) < 0.2 )

  	return STATUS_IDLE;

  	return STATUS_NORMAL;

  }

  void SetStatus(DWORD threadId,bool status)

  {

  	EnterCriticalSection(&m_CS);

  	Iterator_ThreadInfoMap i;

  	ThreadInfo info;

  	i=m_threadMap.find(threadId);

  	info=i->second;

  	info.m_bBusyWorking=status;

  	m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(threadId, info));

  	LeaveCriticalSection(&m_CS);

  }

  void CThreadPool::RemoveThread(DWORDthreadId)

  {

  	EnterCriticalSection(&m_CS);

  	m_threadMap.erase(threadId);

  	LeaveCriticalSection(&m_CS);

  }

  protected:

  	//all the work threads

  	ThreadInfoMap m_threadMap;

  	CRITICAL_SECTION m_CS;

  	HANDLE m_hWorkerIoPort;

  };

  測試代碼

  class CTest:public ITask

  {

  public:

  CTest()
  {
  	static int ii = 0;
  	m_ii = ii ++;
  }

  void ProcessTask(void* pUser)
  {
  	for(int i = 0; i <3; i ++)
  	{
  		cout<<"TaskID: "<<((CTest*)pUser)->m_ii<<endl;
  		Sleep(100);
  	}
  }

  ~CTest()
  {

  }

  private:

  	int m_ii;

  };

  int _tmain(int argc, _TCHAR* argv[])

  {

  	  CThreadPool *pPool= new CThreadPool();

  	  const int TEST_COUNT = 8;

  	  CTest test[TEST_COUNT];

  	  //啟動線程池,5個處理線程,最多接受10個任務

  	  pPool->Start(5,10);

  	  //添加任務到線程池中

  	  for(int i = 0; i < TEST_COUNT; i++)

  	  pPool->AddTask(&test[i], &test[i]);

  	  cin.get();

  	  //停止線程池

  	  pPool->Stop();

  	  return 0;

  }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值