线程池例程

来源:互联网 发布:北京二手房成交数据 编辑:程序博客网 时间:2024/05/17 09:11
  1. 类定义如下
  2. // ThreadPoolImp.h: interface for the ThreadPoolImp class.
  3. //
  4. //////////////////////////////////////////////////////////////////////
  5. #if !defined(AFX_THREADPOOLIMP_H__82F4FC7E_2DB4_4D2A_ACC8_2EFC787CAE42__INCLUDED_)
  6. #define AFX_THREADPOOLIMP_H__82F4FC7E_2DB4_4D2A_ACC8_2EFC787CAE42__INCLUDED_
  7. #if _MSC_VER > 1000
  8. #pragma once
  9. #endif // _MSC_VER > 1000
  10. #pragma warning( disable : 4705 4786)
  11. #include <map>
  12. #include "AutoLock.h"
  13. using namespace std;
  14. class IJobDesc;
  15. class IWorker;
  16. class CThreadPoolImp 
  17. {
  18. public:
  19. class ThreadInfo
  20. {
  21. public:
  22. ThreadInfo() { m_hThread=0; m_bBusyWorking=false; }
  23. ThreadInfo(HANDLE handle, bool bBusy) { m_hThread=handle; m_bBusyWorking=bBusy; }
  24. ThreadInfo(const ThreadInfo& info) { m_hThread=info.m_hThread; m_bBusyWorking=info.m_bBusyWorking; }
  25. ////////
  26. HANDLE m_hThread;
  27. boolm_bBusyWorking;
  28. };
  29. typedef map<DWORD,ThreadInfo> ThreadInfoMap;
  30. typedef ThreadInfoMap::iterator Iterator_ThreadInfoMap;
  31. friend static unsigned int CThreadPoolImp::ManagerProc(void* p); 
  32. friend static unsigned int CThreadPoolImp::WorkerProc(void* p);
  33. protected:
  34. enum ThreadPoolStatus { BUSY, IDLE, NORMAL };
  35. public:
  36. //interface to the outside
  37. void Start(unsigned short nStatic, unsigned short nmax);
  38. void Stop(bool bHash=false);
  39. void ProcessJob(IJobDesc* pJob, IWorker* pWorker) const;
  40. //constructor and destructor
  41. CThreadPoolImp();
  42. virtual ~CThreadPoolImp();
  43. protected:
  44. //interfaces public:
  45. HANDLE GetMgrIoPort() const { return m_hMgrIoPort; }
  46. UINT GetMgrWaitTime() const { return 1000; }
  47. HANDLE GetWorkerIoPort() const { return m_hWorkerIoPort; }
  48. private:
  49. static DWORD WINAPI ManagerProc(void* p);
  50. static DWORD WINAPI WorkerProc(void* p);
  51. protected:
  52. //manager thread
  53. HANDLE m_hMgrThread;
  54. HANDLE m_hMgrIoPort;
  55. protected:
  56. //configuration parameters
  57. mutable unsigned short m_nNumberOfStaticThreads;
  58. mutable unsigned short m_nNumberOfTotalThreads;
  59. protected:
  60. //helper functions
  61. void AddThreads();
  62. void RemoveThreads();
  63. ThreadPoolStatus GetThreadPoolStatus();
  64. void ChangeStatus(DWORD threadId, bool status);
  65. void RemoveThread(DWORD threadId);
  66. protected:
  67. //all the work threads
  68. ThreadInfoMap m_threadMap;
  69. CCriticalSection m_arrayCs;
  70. HANDLE m_hWorkerIoPort;
  71. };
  72. #endif // !defined(AFX_THREADPOOLIMP_H__82F4FC7E_2DB4_4D2A_ACC8_2EFC787CAE42__INCLUDED_)
  73. 实现如下
  74. // ThreadPool.cpp: implementation of the CThreadPoolImp class.
  75. //
  76. //////////////////////////////////////////////////////////////////////
  77. #include "stdafx.h"
  78. #include "ThreadPoolimp.h"
  79. #include "outdebug.h"
  80. #include <assert.h>
  81. #include "work.h"
  82. #ifdef _DEBUG
  83. #undef THIS_FILE
  84. static char THIS_FILE[]=__FILE__;
  85. //#define new DEBUG_NEW
  86. #endif
  87. CThreadPoolImp::CThreadPoolImp()
  88. {
  89. }
  90. CThreadPoolImp::~CThreadPoolImp()
  91. {
  92. }
  93. void CThreadPoolImp::Start(unsigned short nStatic, unsigned short nMax)
  94. {
  95. assert(nMax>=nStatic);
  96. HANDLE hThread;
  97. DWORDnThreadId;
  98. m_nNumberOfStaticThreads=nStatic;
  99. m_nNumberOfTotalThreads=nMax;
  100. //lock the resource
  101. CAutoLock AutoLock(m_arrayCs);
  102. //create an IO port
  103. m_hMgrIoPort = CreateIoCompletionPort((HANDLE)INVALID_HANDLE_VALUE, NULL, 0, 0);
  104. hThread = CreateThread(
  105. NULL, // SD
  106. 0, // initial stack size
  107. (LPTHREAD_START_ROUTINE)ManagerProc, // thread function
  108. (LPVOID)this// thread argument
  109. 0, // creation option
  110. &nThreadId ); // thread identifier
  111. m_hMgrThread = hThread;
  112. //now we start these worker threads
  113. m_hWorkerIoPort = CreateIoCompletionPort((HANDLE)INVALID_HANDLE_VALUE, NULL, 0, 0);
  114. for(long n = 0; n < nStatic; n )
  115. {
  116. hThread = CreateThread(
  117. NULL, // SD
  118. 0, // initial stack size
  119. (LPTHREAD_START_ROUTINE)WorkerProc, // thread function
  120. (LPVOID)this// thread argument
  121. 0, // creation option
  122. &nThreadId ); 
  123. ReportDebug("generate a worker thread handle id is d./n", nThreadId);
  124. m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(nThreadId,ThreadInfo(hThread, false)));
  125. }
  126. }
  127. void CThreadPoolImp::Stop(bool bHash)
  128. {
  129. CAutoLock Lock(m_arrayCs);
  130. ::PostQueuedCompletionStatus(m_hMgrIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFF);
  131. WaitForSingleObject(m_hMgrThread, INFINITE);
  132. CloseHandle(m_hMgrThread);
  133. CloseHandle(m_hMgrIoPort);
  134. //shut down all the worker threads
  135. UINT nCount=m_threadMap.size();
  136. HANDLE* pThread = new HANDLE[nCount];
  137. long n=0;
  138. ThreadInfo info;
  139. Iterator_ThreadInfoMap i=m_threadMap.begin();
  140. while(i!=m_threadMap.end())
  141. {
  142. ::PostQueuedCompletionStatus(m_hWorkerIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFF);
  143. info=i->second;
  144. pThread[n ]=info.m_hThread;
  145. i ;
  146. }
  147. DWORD rc=WaitForMultipleObjects(nCount, pThread, TRUE, 30000);//wait for 0.5 minutes, then start to kill threads
  148. CloseHandle(m_hWorkerIoPort);
  149. if(rc>=WAIT_OBJECT_0 && rc<WAIT_OBJECT_0 nCount)
  150. {
  151. for(unsigned int n=0;n<nCount;n )
  152. {
  153. CloseHandle(pThread[n]);
  154. }
  155. }
  156. else if(rc==WAIT_TIMEOUT&&bHash)
  157. {
  158. //some threads not terminated, we have to stop them.
  159. DWORD exitCode;
  160. for(unsigned int i=0; i<nCount; i )
  161. {
  162. if (::GetExitCodeThread(pThread[i], &exitCode)==STILL_ACTIVE)
  163. {
  164. TerminateThread(pThread[i], 99);
  165. }
  166. CloseHandle(pThread[i]);
  167. }
  168. }
  169. delete[] pThread;
  170. }
  171. DWORD WINAPI CThreadPoolImp::ManagerProc(void* p)
  172. {
  173. //convert the parameter to the server pointer.
  174. CThreadPoolImp* pServer=(CThreadPoolImp*)p;
  175. HANDLEIoPort= pServer->GetMgrIoPort();
  176. unsigned longpN1, pN2; 
  177. OVERLAPPED*pOverLapped;
  178. LABEL_MANAGER_PROCESSING:
  179. while(::GetQueuedCompletionStatus(IoPort, &pN1, &pN2, 
  180. &pOverLapped, pServer->GetMgrWaitTime() ))
  181. {
  182. if(pOverLapped == (OVERLAPPED*)0xFFFFFFFF)
  183. {
  184. return 0;
  185. }
  186. //else if(pOverLapped == (OVERLAPPED*)0xFFFFFFFE)
  187. //{
  188. //if(pN1!=0)
  189. //{
  190. //DWORD rc=::WaitForSingleObject((HANDLE)pN1,INFINITE);
  191. //if(rc=WAIT_OBJECT_0)
  192. //{
  193. //CloseHandle((HANDLE)pN1);//关闭该线程句柄
  194. //}
  195. //ReportDebug("Wait a Thread Removed!/n");
  196. //}
  197. //}
  198. else 
  199. {
  200. ReportDebug("mgr events comes in!/n");
  201. }
  202. }
  203. //time out processing
  204. if (::GetLastError()==WAIT_TIMEOUT)
  205. {
  206. //time out processing
  207. ReportDebug("Time out processing!/n");
  208. //the manager will take a look at all the worker's status. The
  209. if (pServer->GetThreadPoolStatus()==CThreadPoolImp::BUSY)
  210. pServer->AddThreads();
  211. if (pServer->GetThreadPoolStatus()==CThreadPoolImp::IDLE)
  212. pServer->RemoveThreads();
  213. goto LABEL_MANAGER_PROCESSING;
  214. }
  215. return 0;
  216. }
  217. DWORD WINAPI CThreadPoolImp::WorkerProc(void* p)
  218. {
  219. //convert the parameter to the server pointer.
  220. CThreadPoolImp* pServer=(CThreadPoolImp*)p;
  221. HANDLEIoPort= pServer->GetWorkerIoPort();
  222. unsigned longpN1, pN2; 
  223. OVERLAPPED*pOverLapped;
  224. DWORD threadId=::GetCurrentThreadId();
  225. ReportDebug("worker thread id is d./n", threadId);
  226. while(::GetQueuedCompletionStatus(IoPort, &pN1, &pN2, 
  227. &pOverLapped, INFINITE ))
  228. {
  229. if(pOverLapped == (OVERLAPPED*)0xFFFFFFFE)
  230. {
  231. //CThreadPoolImp::Iterator_ThreadInfoMap it=pServer->m_threadMap.find(threadId);
  232. //if(it!=pServer->m_threadMap.end())
  233. //{
  234. //::PostQueuedCompletionStatus(pServer->m_hMgrIoPort,
  235. //(unsigned long)it->second.m_hThread,
  236. //0, 
  237. //(OVERLAPPED*)0xFFFFFFFE);
  238. pServer->RemoveThread(threadId);
  239. //ReportDebug("Try to Remove a Thread/n");
  240. //}
  241. break;
  242. }
  243. else if(pOverLapped == (OVERLAPPED*)0xFFFFFFFF)
  244. {
  245. break;
  246. }
  247. else
  248. {
  249. ReportDebug("worker events comes in!/n");
  250. //before processing, we need to change the status to busy.
  251. pServer->ChangeStatus(threadId, true);
  252. //retrieve the job description and agent pointer
  253. IWorker* pIWorker = reinterdivt_cast<IWorker*>(pN1);
  254. IJobDesc* pIJob= reinterdivt_cast<IJobDesc*>(pN2);
  255. pIWorker->ProcessJob(pIJob);
  256. pServer->ChangeStatus(threadId, false);
  257. }
  258. }
  259. return 0;
  260. }
  261. void CThreadPoolImp::ChangeStatus(DWORD threadId, bool status)
  262. {
  263. CAutoLock CAutoLock(m_arrayCs);
  264. //retrieve the current thread handle
  265. Iterator_ThreadInfoMap i;
  266. ThreadInfo info;
  267. i=m_threadMap.find(threadId);
  268. info=i->second;
  269. //m_threadMap.Lookup(threadId, info);
  270. info.m_bBusyWorking=status;
  271. m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(threadId, info));
  272. }
  273. void CThreadPoolImp::ProcessJob(IJobDesc* pJob, IWorker* pWorker) const
  274. {
  275. ::PostQueuedCompletionStatus(m_hWorkerIoPort, /
  276. reinterdivt_cast<DWORD>(pWorker), /
  277. reinterdivt_cast<DWORD>(pJob),/
  278. NULL);
  279. }
  280. void CThreadPoolImp::AddThreads()
  281. {
  282. HANDLE hThread;
  283. DWORDnThreadId;
  284. unsigned int nCount=m_threadMap.size();
  285. unsigned int nTotal=min(nCount 2, m_nNumberOfTotalThreads);
  286. for(unsigned int i=0; i<nTotal-nCount; i )
  287. {
  288. hThread = CreateThread(
  289. NULL, // SD
  290. 0, // initial stack size
  291. (LPTHREAD_START_ROUTINE)WorkerProc, // thread function
  292. (LPVOID)this// thread argument
  293. 0, // creation option
  294. &nThreadId ); 
  295. ReportDebug("generate a worker thread handle id is d./n", nThreadId);
  296. m_threadMap.insert(m_threadMap.end(),ThreadInfoMap::value_type(nThreadId,ThreadInfo(hThread, false)));
  297. }
  298. }
  299. void CThreadPoolImp::RemoveThread(DWORD threadId)
  300. {
  301. CAutoLock lock(m_arrayCs);
  302. m_threadMap.erase(threadId);
  303. }
  304. void CThreadPoolImp::RemoveThreads()
  305. {
  306. unsigned int nCount=m_threadMap.size();
  307. unsigned int nTotal=max(nCount-2, m_nNumberOfStaticThreads);
  308. for(unsigned int i=0; i<nCount-nTotal; i )
  309. {
  310. ::PostQueuedCompletionStatus(m_hWorkerIoPort, 0, 0, (OVERLAPPED*)0xFFFFFFFE);
  311. }
  312. }
  313. CThreadPoolImp::ThreadPoolStatus CThreadPoolImp::GetThreadPoolStatus()
  314. {
  315. int nTotal = m_threadMap.size();
  316. ThreadInfo info;
  317. int nCount=0;
  318. Iterator_ThreadInfoMap i=m_threadMap.begin(); 
  319. while(i!=m_threadMap.end())
  320. {
  321. info=i->second;
  322. if (info.m_bBusyWorking==true) nCount ;
  323. i ;
  324. }
  325. if ( nCount/(1.0*nTotal) > 0.8 )
  326. return BUSY;
  327. if ( nCount/ (1.0*nTotal) < 0.2 )
  328. return IDLE;
  329. return NORMAL;
  330. }
原创粉丝点击