线程池这个概念在很多地方都有,各种各样的版本。线程池的概念就是预先产生一些等待状态的线程,到有任务到来的时候,就通过某种方法激活空闲的线程去干活。线程忙完之后就又回到等待状态。ms也给我们提供了线程池的api。涉及到的api主要有这些。
- CloseThreadpool
- CloseThreadpoolCleanupGroup
- CloseThreadpoolCleanupGroupMembers
- CloseThreadpoolWait
- CloseThreadpoolWork
- CreateThreadpool
- CreateThreadpoolCleanupGroup
- CreateThreadpoolTimer
- CreateThreadpoolWait
- CreateThreadpoolWork
- InitializeThreadpoolEnvironment
- SetThreadpoolCallbackCleanupGroup
- SetThreadpoolCallbackPool
- SetThreadpoolThreadMaximum
- SetThreadpoolThreadMinimum
- SetThreadpoolTimer
- SetThreadpoolWait
- SubmitThreadpoolWork
- WaitForThreadpoolWaitCallbacks ms应该是使用workitem的这个东西实现的,具体没有研究过。感兴趣的可以看一下msdn。对于这个线程池这个东西c++的版本也有不少。我自己也实现了一份。在这里就贴主要的实现部分。具体的请查看我资源中ui-mgr-task(v2.0)及以上的源代码吧。
#ifndef _BASE_THREAD_H_ #define _BASE_THREAD_H_ #pragma once class ITask; class CBaseThreadPool; class CBaseThread { public: CBaseThread(CBaseThreadPool* pThreadPool); virtual ~CBaseThread(void); public: void Execute(ITask* Task); virtual long WaitForTask(); virtual long DoRealWork(); static ULONG WINAPI ThreadProc(void * Param); CBaseThreadPool* GetThreadPool(){return m_pThreadPool;} long Shutdown(); bool IsShutdown(){return m_bShutdown;} private: CBaseThread(void); CBaseThread(const CBaseThread& ); CBaseThread& operator=(const CBaseThread& ); private: CBaseThreadPool* m_pThreadPool; ITask* m_pTask; HANDLE m_hThread; HANDLE m_hGotTaskEvent; bool m_bShutdown; }; #endif //_BASE_THREAD_H_
#include <assert.h> #include "BaseThreadPool.h" #include "BaseThread.h" #include "ITask.h" CBaseThread::CBaseThread(CBaseThreadPool* pThreadPool) { m_pThreadPool = pThreadPool; m_pTask = NULL; m_hGotTaskEvent = ::CreateEvent(NULL,FALSE,FALSE,NULL); m_hThread = ::CreateThread(NULL,0,ThreadProc,this,CREATE_SUSPENDED,NULL); ::ResumeThread(m_hThread); m_bShutdown = false; } CBaseThread::~CBaseThread(void) { m_bShutdown = true; // ::WaitForSingleObject(m_hThread,10000); // ::TerminateThread(m_hThread,1); ::CloseHandle(m_hThread); ::CloseHandle(m_hGotTaskEvent); } void CBaseThread::Execute(ITask* Task) { m_pThreadPool->AddToRun(this); m_pTask = Task; SetEvent(m_hGotTaskEvent); } long CBaseThread::DoRealWork() { m_pTask->AddToRun(); m_pTask->Work(); m_pTask->RemoveFromRun(); m_pTask->Release(); m_pTask = NULL; m_pThreadPool->AddToIdle(this); return S_OK; } long CBaseThread::WaitForTask() { if(m_pTask) { ResetEvent(m_hGotTaskEvent); return 1; } else { for (int i = 0;!m_bShutdown && !m_pTask && i < 50; ++i) { if(::WaitForSingleObject(m_hGotTaskEvent,100) == WAIT_OBJECT_0) { return 1; } } } return 0; } long CBaseThread::Shutdown() { m_bShutdown = true; if(m_pTask) { m_pTask->Abort(); ::WaitForSingleObject(m_hThread,INFINITE); } return S_OK; } ULONG WINAPI CBaseThread::ThreadProc(void * Param) { assert(Param); CBaseThread* pThread = reinterpret_cast<CBaseThread*>(Param); _BEG: //等待是否这个线程会被再次调度 while(!pThread->IsShutdown() && pThread->WaitForTask()) { pThread->DoRealWork(); } //注意后面成功之后不能再次应用这个Thread了 if(!pThread->IsShutdown() && !pThread->GetThreadPool()->DestoryThread(pThread)) goto _BEG; return S_OK; }
#ifndef _BASE_THREAD_POOL_H_ #define _BASE_THREAD_POOL_H_ #pragma once #include <list> #include <Windows.h> class CBaseThread; class CBaseThreadPool { public: typedef std::list<CBaseThread*> THREAD_QUEUE; public: CBaseThreadPool(void); CBaseThreadPool(ULONG dwMaxThreadNum,ULONG dwMinThreadNum); virtual ~CBaseThreadPool(void); public: void Initialize(); void Uninitialize(); CBaseThread* GetIdleThread(); virtual bool DestoryThread(CBaseThread* Thread); virtual CBaseThread* CreateThread(); void AddToIdle(CBaseThread*); void AddToRun(CBaseThread*); void Shutdown(); protected: void _RemoveFromRun(CBaseThread* Thread); void _RemoveFromIdle(CBaseThread* Thread); private: THREAD_QUEUE m_RunThreadQueue; CRITICAL_SECTION m_RunLock; THREAD_QUEUE m_IdleThreadQueue; CRITICAL_SECTION m_IdleLock; HANDLE m_hAddIdleEvent; ULONG m_dwMaxThreadNum; ULONG m_dwMinThreadNum; bool m_bShutdown; }; #endif //_BASE_THREAD_POOL_H_
#include <algorithm> #include "Lock.h" #include "BaseThread.h" #include "BaseThreadPool.h" CBaseThreadPool::CBaseThreadPool(void) { Initialize(); } CBaseThreadPool::CBaseThreadPool(ULONG dwMaxThreadNum,ULONG dwMinThreadNum) { Initialize(); m_dwMaxThreadNum = dwMaxThreadNum; m_dwMinThreadNum = dwMinThreadNum; } CBaseThreadPool::~CBaseThreadPool(void) { Uninitialize(); } void CBaseThreadPool::Initialize() { m_bShutdown = false; m_dwMaxThreadNum = 2; m_dwMinThreadNum = 1; InitializeCriticalSection(&m_IdleLock); InitializeCriticalSection(&m_RunLock); m_hAddIdleEvent = ::CreateEvent(NULL,TRUE,FALSE,NULL); } void CBaseThreadPool::Uninitialize() { Shutdown(); DeleteCriticalSection(&m_IdleLock); DeleteCriticalSection(&m_RunLock); CloseHandle(m_hAddIdleEvent); } CBaseThread* CBaseThreadPool::GetIdleThread() { CBaseThread* Thread = NULL; if(m_bShutdown) return NULL; if(m_IdleThreadQueue.empty()) { //判断当前正在运行的线程数,根据情况是否需要增加线程或者等待 //wait,注意这里的锁会不会造成长时间等待,或者死锁 if(m_IdleThreadQueue.size() + m_RunThreadQueue.size() < m_dwMaxThreadNum) { CBaseThread* pNewThread = CreateThread(); return pNewThread; } else { while(!m_bShutdown && ::WaitForSingleObject(m_hAddIdleEvent,100) == WAIT_TIMEOUT) { ResetEvent(m_hAddIdleEvent); CAutoLock Lock2(&m_IdleLock); if(!m_IdleThreadQueue.empty()) { Thread = m_IdleThreadQueue.front(); m_IdleThreadQueue.pop_front(); } } } } else { CAutoLock Lock(&m_IdleLock); Thread = m_IdleThreadQueue.front(); m_IdleThreadQueue.pop_front(); } return Thread; } bool CBaseThreadPool::DestoryThread(CBaseThread* Thread) { if (m_bShutdown) { delete Thread; Thread = NULL; return true; } //判断当前idle中的数量 CAutoLockEx lock(&m_IdleLock); lock.Lock(); if(m_IdleThreadQueue.size() > m_dwMinThreadNum) { _RemoveFromIdle(Thread); lock.Unlock(); delete Thread; Thread = NULL; return true; } lock.Unlock(); return false; } CBaseThread* CBaseThreadPool::CreateThread() { return new CBaseThread(this); } void CBaseThreadPool::AddToIdle(CBaseThread* Thread) { //从run中删除之后在添加 _RemoveFromRun(Thread); CAutoLock Lock(&m_IdleLock); m_IdleThreadQueue.push_back(Thread); ::SetEvent(m_hAddIdleEvent); } void CBaseThreadPool::AddToRun(CBaseThread* Thread) { CAutoLock Lock(&m_RunLock); m_RunThreadQueue.push_back(Thread); } void CBaseThreadPool::_RemoveFromRun(CBaseThread* Thread) { if(m_bShutdown) return; CAutoLock Lock(&m_RunLock); THREAD_QUEUE::iterator it = find(m_RunThreadQueue.begin(),m_RunThreadQueue.end(),Thread); if(it!=m_RunThreadQueue.end()) { m_RunThreadQueue.erase(it); } } void CBaseThreadPool::_RemoveFromIdle(CBaseThread* Thread) { if(m_bShutdown) return; CAutoLock Lock(&m_IdleLock); THREAD_QUEUE::iterator it = find(m_IdleThreadQueue.begin(),m_IdleThreadQueue.end(),Thread); if(it!=m_IdleThreadQueue.end()) { m_IdleThreadQueue.erase(it); } } void CBaseThreadPool::Shutdown() { m_bShutdown = true; m_dwMinThreadNum = m_dwMaxThreadNum = 0; CAutoLockEx lock(&m_RunLock); lock.Lock(); THREAD_QUEUE::iterator it = m_RunThreadQueue.begin(); while(it!=m_RunThreadQueue.end()) { (*it)->Shutdown(); //需要进一步检查,判断是否有可能出现死锁 ++it; } m_RunThreadQueue.clear(); lock.Unlock(); CAutoLockEx lock2(&m_IdleLock); lock2.Lock(); it = m_IdleThreadQueue.begin(); while (it!=m_IdleThreadQueue.end()) { DestoryThread(*it); ++it; } m_IdleThreadQueue.clear(); lock2.Unlock(); }