[C++][线程池][完整实现] 转:线程池原理及创建(C++实现)

文章的主要框架是参考这篇文档的,http://jacky-dai.iteye.com/blog/1090285,

关于作者 

张中庆,西安交通大学软件所,在读硕士,目前研究方向为分布式网络与移动中间件,对Linux极其爱好,可以通过[email protected]与我联系

其实看了好多类似的,都是没有完整的实现,自己花了点时间把这个程序梳理了一下,写了个测试程序,目前可以跑通。

[html]  view plain  copy
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <vector>  
  4. #include <algorithm>  
  5. #include <assert.h>  
  6. #include <Windows.h>  
  7. #include <functional>  
  8. #include <process.h>  
  9.   
  10. using namespace std;  
  11. class CThread;  
  12.   
  13. //锁的基类  
  14. class CLockObject  
  15. {  
  16. public:  
  17.     virtual BOOL Lock() = 0;  
  18.     virtual BOOL UnLock() = 0;  
  19. };  
  20.   
  21. //任务基类,所有要执行的任务都继承这个类  
  22. class CJob  
  23. {  
  24. private:  
  25.     int      m_JobNo;//任务ID 用来调试是否绑定特定线程  
  26.     char*    m_JobName; //任务名字,用来调试是否绑定特定线程  
  27.     CThread* m_pWorkThread; //The thread associated with the job   
  28. public:  
  29.     CJob();   
  30.     virtual ~CJob();  
  31.     CThread *GetWorkThread(void); //获取工作线程  
  32.     void SetWorkThread(CThread* pWorkThread);//设置工作线程  
  33.     virtual void Execute(void* ptr) = 0; //执行函数  
  34.     int      GetJobNo(void) const { return m_JobNo; }    
  35.     void     SetJobNo(int jobno){ m_JobNo = jobno;}    
  36.     char*    GetJobName(void) const { return m_JobName; }    
  37.     void     SetJobName(char* jobname);  
  38. };  
  39.   
  40. void CJob::SetJobName(char* jobname)    
  41. {    
  42.     if(NULL !=m_JobName)  
  43.     {    
  44.         free(m_JobName);    
  45.         m_JobName = NULL;    
  46.     }    
  47.   
  48.     if(NULL !=jobname)   
  49.     {    
  50.         m_JobName = (char*)malloc(strlen(jobname)+1);    
  51.         strcpy(m_JobName,jobname);    
  52.     }    
  53. }    
  54.   
  55. CThread* CJob::GetWorkThread(void)  
  56. {   
  57.     return m_pWorkThread;   
  58. }   
  59.   
  60. void CJob::SetWorkThread(CThread *pWorkThread)  
  61. {   
  62.     m_pWorkThread = pWorkThread;   
  63. }  
  64.   
  65. CJob::CJob(void) :m_pWorkThread(NULL),m_JobName(NULL), m_JobNo(0)  
  66. {   
  67.   
  68. }   
  69.   
  70. CJob::~CJob()  
  71. {   
  72.     if (NULL != m_JobName)  
  73.     {  
  74.         free(m_JobName);  
  75.         m_JobName = NULL;  
  76.     }  
  77. }   
  78.   
  79. //线程状态  
  80. typedef enum _ThreadState  
  81. {  
  82.     THREAD_RUNNING = 0x0, //运行  
  83.     THREAD_IDLE = 0x1,//空闲  
  84.     THREAD_EXIT = 0X2,//退出  
  85. }ThreadState;  
  86.   
  87. //线程基类  
  88. class CThread  
  89. {  
  90. private:  
  91.     int m_ErrorCode; //错误码  
  92.     unsigned long m_ThreadID; //线程ID  
  93.     char* m_ThreadName; //线程名字  
  94.     ThreadState m_ThreadState; //线程状态  
  95.     HANDLE m_hthreadHandle; //线程句柄  
  96.     bool      m_IsExit;//是否退出  
  97. protected:  
  98.     static unsigned __stdcall ThreadFunction(void*); //start调用此函数,此函数再调用run函数,执行实际的任务  
  99. public:  
  100.     CThread();  
  101.     virtual ~CThread();  
  102.   
  103.     virtual void Run() = 0;  
  104.   
  105.     //设置线程状态  
  106.     void SetThreadState(ThreadState state);  
  107.     //获取线程状态  
  108.     ThreadState GetThreadState();  
  109.   
  110.     //Start to execute the thread   
  111.     bool Start();  
  112.   
  113.     //获取线程ID  
  114.     int GetThreadID(void);  
  115.   
  116.     //设置错误码  
  117.     void SetErrorCode(int errorCode);  
  118.     //获取错误码  
  119.     int GetLastError(void);  
  120.   
  121.     //设置线程名字  
  122.     void SetThreadName(char* threadName);  
  123.     //获取线程名字  
  124.     char* GetThreadName();  
  125.   
  126.     //设置线程优先级  
  127.     bool     SetPriority(int priority);   
  128.     //获取线程优先级  
  129.     int      GetPriority(void);   
  130.   
  131.     bool     Terminate(void);  
  132.     HANDLE GetThreadHandle();  
  133.     void SetThreadHandle(HANDLE hdl);  
  134.     void SetExitFlag(bool bExit);  
  135.     bool GetExitFlag();  
  136.     bool NeedExit();  
  137. };  
  138.   
  139. bool CThread::NeedExit()  
  140. {  
  141.     return m_IsExit;  
  142. }  
  143.   
  144. void CThread::SetExitFlag(bool bExit)  
  145. {  
  146.     m_IsExit = bExit;  
  147. }  
  148.   
  149. bool CThread::GetExitFlag()  
  150. {  
  151.     return m_IsExit;  
  152. }  
  153.   
  154. bool CThread::Terminate(void)  
  155. {  
  156.     _endthreadex(0);  
  157.     return TRUE;  
  158. }  
  159.   
  160. HANDLE CThread::GetThreadHandle()  
  161. {  
  162.     return m_hthreadHandle;  
  163. }  
  164.   
  165. void CThread::SetThreadHandle(HANDLE hdl)  
  166. {  
  167.     m_hthreadHandle = hdl;  
  168. }  
  169.   
  170. void CThread::SetErrorCode(int errorCode)   
  171. {  
  172.     m_ErrorCode = errorCode;  
  173. }  
  174.   
  175. int CThread::GetLastError(void)  
  176. {  
  177.     return m_ErrorCode;  
  178. }  
  179.   
  180. CThread::CThread()  
  181. {  
  182.     m_IsExit = FALSE;  
  183. }  
  184.   
  185. CThread::~CThread()  
  186. {  
  187.   
  188. }  
  189.   
  190. void CThread::SetThreadState(ThreadState state)  
  191. {  
  192.     m_ThreadState = state;  
  193. }  
  194.   
  195. ThreadState CThread::GetThreadState()  
  196. {  
  197.     return m_ThreadState;  
  198. }  
  199.   
  200. //Start to execute the thread   
  201. bool CThread::Start()  
  202. {  
  203.     unsigned threadID;  
  204.     HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, this, 0, &threadID);  
  205.     this->m_ThreadID = threadID;  
  206.     this->SetThreadHandle(hThread);  
  207.     return true;  
  208. }  
  209.   
  210. unsigned __stdcall CThread::ThreadFunction(void* pArg)  
  211. {  
  212.     CThread* pThread = (CThread*)pArg;  
  213.     pThread->Run();  
  214.     return TRUE;  
  215. }  
  216.   
  217. int  CThread::GetThreadID(void)  
  218. {  
  219.     return m_ThreadID;  
  220. }  
  221.   
  222. void CThread::SetThreadName(char* threadName)  
  223. {  
  224.     strncpy(m_ThreadName, threadName, strlen(threadName));  
  225. }  
  226.   
  227. char* CThread::GetThreadName()  
  228. {  
  229.     return m_ThreadName;  
  230. }  
  231.   
  232. //线程互斥锁  
  233. class CThreadMutex: public CLockObject  
  234. {  
  235. private:  
  236.     CRITICAL_SECTION m_CritSec;//临界区  
  237. public:  
  238.     CThreadMutex();  
  239.     ~CThreadMutex();  
  240.     BOOL Lock();//加锁,阻塞式  
  241.     BOOL UnLock();//解锁  
  242.     BOOL TryLock();//加锁,非阻塞式  
  243. };  
  244.   
  245. CThreadMutex::CThreadMutex()  
  246. {  
  247. #if (_WIN32_WINNT >= 0x0403)  
  248.     //使用 InitializeCriticalSectionAndSpinCount 可以提高性能  
  249.     ::InitializeCriticalSectionAndSpinCount(&m_CritSec,4000);  
  250. #else  
  251.     ::InitializeCriticalSection(&m_CritSec);  
  252. #endif  
  253. }  
  254.   
  255. CThreadMutex::~CThreadMutex()  
  256. {  
  257.     ::DeleteCriticalSection(&m_CritSec);  
  258. }  
  259.   
  260. BOOL CThreadMutex::Lock()  
  261. {  
  262.     ::EnterCriticalSection(&m_CritSec);  
  263.     return TRUE;  
  264. }  
  265.   
  266. BOOL CThreadMutex::UnLock()  
  267. {  
  268.     ::LeaveCriticalSection(&m_CritSec);  
  269.     return TRUE;  
  270. }  
  271.   
  272. BOOL CThreadMutex::TryLock()  
  273. {  
  274.     BOOL bRet = TryEnterCriticalSection(&m_CritSec);  
  275.     return bRet;  
  276. }  
  277.   
  278. //条件变量  
  279. class CThreadCondition  
  280. {  
  281. private:  
  282.     HANDLE m_phEvent; //句柄  
  283. public:  
  284.     CThreadCondition();  
  285.     ~CThreadCondition();  
  286.     void Wait();  
  287.     void Signal();  
  288. };  
  289.   
  290. CThreadCondition::CThreadCondition()  
  291. {  
  292.     //第二个参数 bManualReset FALSE the system automatically resets the state to nonsignaled  
  293.     //If this parameter is TRUE, the function creates a manual-reset event object  
  294.     //第三个参数 bInitialState FALSE it is nonsignaled  
  295.     m_phEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);  
  296. }  
  297.   
  298. CThreadCondition::~CThreadCondition()  
  299. {  
  300.     if (NULL != m_phEvent)  
  301.     {  
  302.         ::CloseHandle((m_phEvent));  
  303.     }  
  304. }  
  305.   
  306. void CThreadCondition::Wait()  
  307. {  
  308.     //If dwMilliseconds is INFINITE, the function will return only when the object is signaled.  
  309.     WaitForSingleObject(m_phEvent, INFINITE);  
  310.     ResetEvent(m_phEvent);  
  311. }  
  312.   
  313. void CThreadCondition::Signal()  
  314. {  
  315.     //Sets the specified event object to the signaled state  
  316.     SetEvent(m_phEvent);  
  317. }  
  318.   
  319. //线程池类,主要负责调度线程,创建线程,删除线程  
  320. class CThreadPool  
  321. {  
  322.     friend class CWorkerThread;  
  323. private:  
  324.     unsigned int m_nMaxNum; //当前线程池中所允许并发存在的线程的最大数目   
  325.     unsigned int m_nAvailLow; //当前线程池中所允许存在的空闲线程的最小数目   
  326.     //如果空闲数目低于该值,表明负载可能过重,此时有必要增加空闲线程池的数目  
  327.     //实现中我们总是将线程调整为m_InitNum个  
  328.     unsigned int m_nAvailHigh;//当前线程池中所允许的空闲的线程的最大数目,  
  329.     //如果空闲数目高于该值,表明当前负载可能较轻,此时将删除多余的空闲线程,删除后调整数也为m_InitNum个  
  330.     unsigned int m_nCurIdleThreadsNum;//当前线程池中实际存在的线程的个数,其值介于m_nAvailHigh和m_nAvailLow之间  
  331.     //如果线程的个数始终维持在m_nAvailLow和m_nAvailHigh之间,则线程既不需要创建,也不需要删除,保持平衡状态  
  332.     unsigned int m_nInitThreadsNum;//初始创建时线程池中的线程的个数  
  333.   
  334. protected:  
  335.     CWorkerThread* GetIdleThread(void);//获取空闲线程  
  336.     void    AppendToIdleList(CWorkerThread* jobthread);//线程加入空闲队列  
  337.     void    MoveToBusyList(CWorkerThread* idlethread);//线程加入忙碌队列  
  338.     void    MoveToIdleList(CWorkerThread* busythread);//线程加入空闲队列   
  339.     void    DeleteIdleThread(int num); //删除空闲线程  
  340.     void    CreateIdleThread(int num); //创建空闲线程  
  341.   
  342. public:  
  343.     CThreadMutex m_BusyMutex;//when visit busy list,use m_BusyMutex to Lock and unlock  
  344.     CThreadMutex m_IdleMutex;//when visit idle list,use m_IdleMutex to Lock and unlock  
  345.     CThreadMutex m_ThreadNumMutex;//变量锁, 目前用在m_nCurIdleThreadsNum修改上面  
  346.   
  347.     CThreadCondition m_BusyCond; //m_BusyCond is used to sync busy thread list  
  348.     CThreadCondition m_IdleCond; //m_IdleCond is used to sync idle thread list  
  349.     CThreadCondition m_MaxNumCond;//m_MaxNumCond is used to sync m_nCurIdleThreadsNum  
  350.   
  351.     vector<CWorkerThread*> m_vecAllThreads;//所有创建出来的线程集合  
  352.     vector<CWorkerThread*> m_vecBusyThreads;//忙碌线程队列,随着负载的多少会改变  
  353.     vector<CWorkerThread*> m_vecIdleThreads;//空闲线程队列,随着负的多少会改变  
  354.   
  355. public:  
  356.     void    SetMaxNum(int maxnum){m_nMaxNum = maxnum;} //设置线程池运行的最大线程数  
  357.     int     GetMaxNum(void){return m_nMaxNum;}  
  358.     void    SetAvailLowNum(int minnum){m_nAvailLow = minnum;} //设置最少空闲线程数  
  359.     int     GetAvailLowNum(void){return m_nAvailLow;}   
  360.     void    SetAvailHighNum(int highnum){m_nAvailHigh = highnum;} //设置最多空闲线程数  
  361.     int     GetAvailHighNum(void){return m_nAvailHigh;}   
  362.     int     GetCurIdleThreadsNum(void){return m_nCurIdleThreadsNum;} //获取当前空闲线程个数  
  363.     int     GetAllThreadsNum(void){return m_vecAllThreads.size();} //获取所有线程个数  
  364.     int     GetBusyThreadsNum(void){return m_vecBusyThreads.size();} //获取忙碌空闲线程个数  
  365.     void    SetInitNum(int initnum){m_nInitThreadsNum = initnum;}   
  366.     int     GetInitNum(void){return m_nInitThreadsNum;}   
  367.     CThreadPool();  
  368.     ~CThreadPool();  
  369.     CThreadPool(int initnum);  
  370.     void TerminateAll();  
  371.     void Run(CJob* job,void* jobdata);  
  372. };  
  373.   
  374. //真正的工作线程,执行操作的线程  
  375. class CWorkerThread : public CThread  
  376. {  
  377. private:  
  378.     CThreadPool* m_pThreadPool;//线程池  
  379.     CJob* m_pJob;//任务  
  380.     void* m_pJobData;//任务参数  
  381.     CThreadMutex m_VarMutex;//  
  382. public:  
  383.     CThreadCondition   m_JobAddCond; //有新的任务时触发条件变量,每个线程一个条件变量,可以指定线程去执行任务  
  384.     CThreadMutex m_WorkMutex;//  
  385.     CWorkerThread();   
  386.     virtual ~CWorkerThread();   
  387.     void Run();   
  388.     void    AddNewJob(CJob* job,void* jobdata);   
  389.     CJob*   GetJob(void){return m_pJob;}   
  390.     void    SetThreadPool(CThreadPool* thrpool);   
  391.     CThreadPool* GetThreadPool(void){return m_pThreadPool;}   
  392.     void Terminate(void);  
  393. };  
  394.   
  395. void CWorkerThread::Terminate(void)  
  396. {  
  397.     //工作线程再处理任务结束才会解锁,这个时候再去退出线程,避免打断线程处理任务。  
  398.     m_WorkMutex.Lock();  
  399.     SetExitFlag(TRUE);  
  400.     //工作为假 代表要求线程退出  
  401.     m_pJob = NULL;   
  402.     m_pJobData = NULL;   
  403.     printf("thread [%d] ready to exit\n", GetThreadID());  
  404.     m_JobAddCond.Signal();  
  405.     m_WorkMutex.UnLock();  
  406.     WaitForSingleObject(GetThreadHandle(), INFINITE);  
  407.     CloseHandle(GetThreadHandle());  
  408. }  
  409.   
  410. CWorkerThread::CWorkerThread()  
  411. {  
  412.     m_pJobData = NULL;  
  413.     m_pJob = NULL;  
  414.     m_pThreadPool = NULL;  
  415. }  
  416.   
  417. CWorkerThread::~CWorkerThread()  
  418. {  
  419.     if (NULL != m_pJob) {delete m_pJob; m_pJob = NULL;}  
  420.     if (NULL != m_pThreadPool) {delete m_pThreadPool; m_pThreadPool = NULL;}  
  421. }  
  422.   
  423. void CWorkerThread::Run()  
  424. {  
  425.     printf("Enter CWorkerThread::Run\n");  
  426.     SetThreadState(THREAD_RUNNING);  
  427.     for(;;)  
  428.     {  
  429.         //当前线程不退出才需要等待任务的到来  
  430.         while ((NULL == m_pJob) && !NeedExit())  
  431.         {  
  432.             printf("thread [%d] wait for job \n", GetThreadID());  
  433.             m_JobAddCond.Wait();  
  434.         }  
  435.   
  436.         if (NULL == m_pJob)  
  437.         {  
  438.             printf("thread [%d] exitFlag [%d]\n", GetThreadID(), NeedExit());  
  439.             if (NeedExit())  
  440.             {  
  441.                 break;//不再等待任务,退出线程  
  442.             }  
  443.             else  
  444.             {  
  445.                 //任务为NULL 但不是线程退出,跳过这个任务  
  446.                 printf("m_pJob [%p] exitFlag [%d]\n", m_pJob, NeedExit());  
  447.                 continue;  
  448.             }  
  449.         }  
  450.   
  451.         m_WorkMutex.Lock();  
  452.         printf("thread [%d] accept the job [%d]\n", GetThreadID(), m_pJob->GetJobNo());  
  453.         //真正执行任务的地方  
  454.         m_pJob->Execute(m_pJobData);   
  455.         m_pJob->SetWorkThread(NULL);   
  456.         m_pJob = NULL;  
  457.         m_pJobData = NULL;  
  458.         m_pThreadPool->MoveToIdleList(this);  
  459.         SetThreadState(THREAD_IDLE);  
  460.         if(m_pThreadPool->m_vecIdleThreads.size() > m_pThreadPool->GetAvailHighNum())   
  461.         {   
  462.             m_pThreadPool->DeleteIdleThread(m_pThreadPool->m_vecIdleThreads.size() - m_pThreadPool->GetInitNum());   
  463.         }  
  464.         m_WorkMutex.UnLock();   
  465.     }  
  466.     printf("thread [%d] exit\n", GetThreadID());  
  467. }  
  468.   
  469. void CWorkerThread::AddNewJob(CJob* pJob,void* jobdata)   
  470. {  
  471.     assert(NULL != pJob);  
  472.     m_VarMutex.Lock();   
  473.     m_pJob = pJob;   
  474.     m_pJobData = jobdata;   
  475.     pJob->SetWorkThread(this);   
  476.     m_VarMutex.UnLock();   
  477.     printf("job [%d] add to the pool\n",m_pJob->GetJobNo());  
  478.     m_JobAddCond.Signal();   
  479. }  
  480.   
  481. void CWorkerThread::SetThreadPool(CThreadPool* thrpool)   
  482. {   
  483.     m_VarMutex.Lock();   
  484.     m_pThreadPool = thrpool;   
  485.     m_VarMutex.UnLock();   
  486. }  
  487.   
  488. CThreadPool::CThreadPool()  
  489. {  
  490.     m_nMaxNum = 50;  
  491.     m_nAvailLow = 5;  
  492.     m_nInitThreadsNum = 10;  
  493.     m_nCurIdleThreadsNum = 10;  
  494.     m_nAvailHigh = 20;  
  495.     m_vecBusyThreads.clear();  
  496.     m_vecIdleThreads.clear();  
  497.     int i;  
  498.     for (i=0; i<m_nInitThreadsNum; ++i)  
  499.     {  
  500.         CWorkerThread* pNewWorkThread = new CWorkerThread;  
  501.         pNewWorkThread->SetThreadPool(this);  
  502.         AppendToIdleList(pNewWorkThread);  
  503.         pNewWorkThread->Start();  
  504.     }  
  505. }  
  506.   
  507. CThreadPool::CThreadPool(int initnum)  
  508. {  
  509.     m_nMaxNum   = 30;   
  510.     m_nAvailLow = (initnum-10>0)?(initnum-10):3;   
  511.     m_nInitThreadsNum = m_nCurIdleThreadsNum = initnum ;    
  512.     m_nAvailHigh = initnum+10;   
  513.     m_vecAllThreads.clear();  
  514.     m_vecBusyThreads.clear();  
  515.     m_vecIdleThreads.clear();  
  516.     int i;  
  517.     for (i=0; i<m_nInitThreadsNum; ++i)  
  518.     {  
  519.         CWorkerThread* pNewWorkThread = new CWorkerThread;  
  520.         pNewWorkThread->SetThreadPool(this);  
  521.         AppendToIdleList(pNewWorkThread);  
  522.         pNewWorkThread->Start();  
  523.     }  
  524.     printf("CThreadPool::CThreadPool: Create Thread [%d] success\n", m_nInitThreadsNum);  
  525. }  
  526.   
  527. CThreadPool::~CThreadPool()  
  528. {  
  529.     TerminateAll();  
  530. }  
  531.   
  532. void CThreadPool::TerminateAll()  
  533. {  
  534.     int i;  
  535.     for (i=0; i<m_vecAllThreads.size(); ++i)  
  536.     {  
  537.         CWorkerThread* pWorkThread = m_vecAllThreads[i];  
  538.         pWorkThread->Terminate();  
  539.     }  
  540. }  
  541.   
  542. //获取空闲的线程  
  543. CWorkerThread* CThreadPool::GetIdleThread(void)   
  544. {  
  545.     while (0 == m_vecIdleThreads.size())  
  546.     {  
  547.         printf("no idle threads, must wait\n");  
  548.         m_IdleCond.Wait();  
  549.     }      
  550.     m_IdleMutex.Lock();  
  551.     if (0 < m_vecIdleThreads.size())  
  552.     {  
  553.         CWorkerThread* pIdleThread = (CWorkerThread*)m_vecIdleThreads.front();  
  554.         printf("get idle thread %d \n", pIdleThread->GetThreadID());  
  555.         m_IdleMutex.UnLock();  
  556.         return pIdleThread;  
  557.     }  
  558.     m_IdleMutex.UnLock();  
  559.     printf("warning: no idle threads return\n");  
  560.     return NULL;  
  561. }  
  562.   
  563. //add an idle thread to idle list  
  564. void CThreadPool::AppendToIdleList(CWorkerThread* jobthread)   
  565. {  
  566.     m_IdleMutex.Lock();   
  567.     m_vecIdleThreads.push_back(jobthread);   
  568.     m_vecAllThreads.push_back(jobthread);   
  569.     m_IdleMutex.UnLock();   
  570. }  
  571.   
  572. //move and idle thread to busy thread   
  573. void CThreadPool::MoveToBusyList(CWorkerThread* idlethread)   
  574. {  
  575.     m_BusyMutex.Lock();   
  576.     m_vecBusyThreads.push_back(idlethread);   
  577.     m_nCurIdleThreadsNum--;   
  578.     m_BusyMutex.UnLock();   
  579.   
  580.     m_IdleMutex.Lock();   
  581.     vector<CWorkerThread*>::iterator pos;   
  582.     pos = find(m_vecIdleThreads.begin(),m_vecIdleThreads.end(),idlethread);   
  583.     if(pos != m_vecIdleThreads.end())   
  584.     {  
  585.         m_vecIdleThreads.erase(pos);   
  586.     }  
  587.     m_IdleMutex.UnLock();   
  588. }  
  589.   
  590. void CThreadPool::MoveToIdleList(CWorkerThread* busythread)   
  591. {   
  592.     m_IdleMutex.Lock();   
  593.     m_vecIdleThreads.push_back(busythread);   
  594.     m_nCurIdleThreadsNum++;   
  595.     m_IdleMutex.UnLock();   
  596.   
  597.     m_BusyMutex.Lock();   
  598.     vector<CWorkerThread*>::iterator pos;   
  599.     pos = find(m_vecBusyThreads.begin(),m_vecBusyThreads.end(),busythread);   
  600.     if(pos!=m_vecBusyThreads.end())   
  601.         m_vecBusyThreads.erase(pos);   
  602.     m_BusyMutex.UnLock();   
  603.     m_IdleCond.Signal();   
  604.     m_MaxNumCond.Signal();  
  605. }   
  606.   
  607. //create num idle thread and put them to idlelist   
  608. void CThreadPool::CreateIdleThread(int num)  
  609. {  
  610.     int i;  
  611.     for (i=0;i<num;i++)  
  612.     {  
  613.         CWorkerThread* pWorkThread = new CWorkerThread();   
  614.         pWorkThread->SetThreadPool(this);   
  615.         AppendToIdleList(pWorkThread);   
  616.         m_ThreadNumMutex.Lock();   
  617.         m_nCurIdleThreadsNum++;   
  618.         m_ThreadNumMutex.UnLock();   
  619.         pWorkThread->Start();//begin the thread,the thread wait for job   
  620.     }  
  621. }  
  622.   
  623. void CThreadPool::DeleteIdleThread(int num)   
  624. {  
  625.     printf("Enter into CThreadPool::DeleteIdleThread\n");   
  626.     m_IdleMutex.Lock();   
  627.     printf("Delete Num is %dn",num);   
  628.     int i;  
  629.     for(i=0;i<num;i++)  
  630.     {   
  631.         CWorkerThread* thr;   
  632.         if(m_vecIdleThreads.size() > 0 )  
  633.         {   
  634.             thr = (CWorkerThread*)m_vecIdleThreads.front();   
  635.             printf("Get Idle thread %dn",thr->GetThreadID());   
  636.         }  
  637.         else  
  638.         {  
  639.             printf("no idle thread, no need to delete thread\n");  
  640.             break;  
  641.         }  
  642.   
  643.         vector<CWorkerThread*>::iterator pos;   
  644.         pos = find(m_vecIdleThreads.begin(),m_vecIdleThreads.end(),thr);   
  645.         if(pos!=m_vecIdleThreads.end())   
  646.             m_vecIdleThreads.erase(pos);   
  647.         m_nCurIdleThreadsNum--;   
  648.         printf("The idle thread available num:%d n",m_nCurIdleThreadsNum);   
  649.         printf("The idlelist              num:%d n",m_vecIdleThreads.size());   
  650.     }   
  651.     m_IdleMutex.UnLock();   
  652. }  
  653.   
  654. void CThreadPool::Run(CJob* job, void* jobdata)  
  655. {  
  656.     assert(NULL != job);  
  657.     //if the busy thread num adds to m_nMaxNum,so we should wait   
  658.     if(m_nMaxNum <= GetBusyThreadsNum())  
  659.     {  
  660.         printf("busy threads beyond the max threads number in the pool, must wait for idle threads\n");  
  661.         m_MaxNumCond.Wait();   
  662.     }  
  663.   
  664.     //负载过重,空闲线程少,需要创建新的线程, 使其数目达到m_InitNum  
  665.     if(m_vecIdleThreads.size() < m_nAvailLow)   
  666.     {   
  667.         if(GetAllThreadsNum()+m_nInitThreadsNum-m_vecIdleThreads.size() < m_nMaxNum )   
  668.         {  
  669.             //当前有m_vecIdleThreads.size()空闲线程, 另外再创建m_nInitThreadsNum - m_vecIdleThreads.size(), 当前总的空闲线程为m_nInitThreadsNum  
  670.             CreateIdleThread(m_nInitThreadsNum - m_vecIdleThreads.size());   
  671.         }  
  672.         else   
  673.         {  
  674.             CreateIdleThread(m_nMaxNum - GetAllThreadsNum());   
  675.         }  
  676.     }  
  677.   
  678.     CWorkerThread*  pWorkthread = GetIdleThread();  
  679.     if(NULL != pWorkthread)   
  680.     {   
  681.         pWorkthread->m_WorkMutex.Lock();   
  682.         MoveToBusyList(pWorkthread);   
  683.         pWorkthread->SetThreadPool(this);   
  684.         job->SetWorkThread(pWorkthread);   
  685.         printf("Job [%d] bind to thread [%d] \n", job->GetJobNo(), pWorkthread->GetThreadID());   
  686.         pWorkthread->AddNewJob(job, jobdata);   
  687.         pWorkthread->m_WorkMutex.UnLock();  
  688.     }  
  689.     else  
  690.     {  
  691.         printf("impossible to going here\n");  
  692.     }  
  693. }  
  694.   
  695. //线程管理类  
  696. class CThreadManage  
  697. {  
  698. public:  
  699.     CThreadManage();  
  700.     CThreadManage(int num);  
  701.     virtual ~CThreadManage();  
  702.     void Run(CJob* pjob, void* pJobData);//运行任务  
  703.     void TerminateAll(); //停止所有的线程  
  704. private:  
  705.     int m_nNumOfThread;  //初始时允许创建的最大的线程个数  
  706.     CThreadPool* m_pPool;//实际的线程池  
  707. };  
  708.   
  709. CThreadManage::CThreadManage()  
  710. {  
  711.     m_nNumOfThread = 10;  
  712.     m_pPool = new CThreadPool(m_nNumOfThread);  
  713. }  
  714.   
  715. CThreadManage::CThreadManage(int num)  
  716. {  
  717.     m_nNumOfThread = num;  
  718.     m_pPool = new CThreadPool(m_nNumOfThread);  
  719. }  
  720.   
  721. CThreadManage::~CThreadManage()  
  722. {  
  723.     if (NULL != m_pPool)  
  724.     {  
  725.         delete m_pPool;  
  726.         m_pPool = NULL;  
  727.     }  
  728. }  
  729.   
  730. void CThreadManage::Run(CJob* pjob, void* pJobData)  
  731. {  
  732.     m_pPool->Run(pjob, pJobData);  
  733. }  
  734.   
  735. void CThreadManage::TerminateAll()  
  736. {  
  737.     m_pPool->TerminateAll();  
  738. }  
  739.   
  740. class myjob : public CJob  
  741. {  
  742. public:   
  743.     myjob(){}   
  744.     myjob(int i){SetJobNo(i);}  
  745.     ~myjob(){}   
  746.     void Execute(void* jobdata)    {   
  747.         printf("The Job comes from CXJOB\n");   
  748.         ::Sleep(2);   
  749.     }  
  750. };  
  751.   
  752. #if 0  
  753. int main()  
  754. {   
  755.     CThreadManage* manage = new CThreadManage(50);   
  756.     for(int i=0;i<1000;i++)   
  757.     {   
  758.         myjob* job = new myjob(i);   
  759.         manage->Run(job, NULL);   
  760.     }   
  761.     ::Sleep(2);   
  762.   
  763.     myjob* job = new myjob();   
  764.     manage->Run(job, NULL);   
  765.     manage->TerminateAll();   
  766.     return 0;  
  767. }   
  768. #endif  

猜你喜欢

转载自blog.csdn.net/leo_888/article/details/80390599
今日推荐