printf(\ idlethr->SetJob(job,jobdata);
} }
在CThreadPool中存在两个链表,一个是空闲链表,一个是忙碌链表。Idle链表中存放所有的空闲进程,当线程执行任务时候,其状态变为忙碌状态,同时从空闲链表中删除,并移至忙碌链表中。在CThreadPool的构造函数中,我们将执行下面的代码:
for(int i=0;i CWorkerThread* thr = new CWorkerThread(); AppendToIdleList(thr); thr->SetThreadPool(this); thr->Start(); //begin the thread,the thread wait for job } 在该代码中,我们将创建m_InitNum个线程,创建之后即调用AppendToIdleList放入Idle链表中,由于目前没有任务分发给这些线程,因此线程执行Start后将自己挂起。 事实上,线程池中容纳的线程数目并不是一成不变的,其会根据执行负载进行自动伸缩。为此在CThreadPool中设定四个变量: m_InitNum:处世创建时线程池中的线程的个数。 m_MaxNum:当前线程池中所允许并发存在的线程的最大数目。 m_AvailLow:当前线程池中所允许存在的空闲线程的最小数目,如果空闲数目低于该值,表明负载可能过重,此时有必要增加空闲线程池的数目。实现中我们总是将线程调整为m_InitNum个。 m_AvailHigh:当前线程池中所允许的空闲的线程的最大数目,如果空闲数目高于该值,表明当前负载可能较轻,此时将删除多余的空闲线程,删除后调整数也为m_InitNum个。 m_AvailNum:目前线程池中实际存在的线程的个数,其值介于m_AvailHigh和m_AvailLow之间。如果线程的个数始终维持在m_AvailLow和m_AvailHigh之间,则线程既不需要创建,也不需要删除,保持平衡状态。因此如何设定m_AvailLow和m_AvailHigh的值,使得线程池最大可能的保持平衡态,是线程池设计必须考虑的问题。 线程池在接受到新的任务之后,线程池首先要检查是否有足够的空闲池可用。检查分为三个步骤: (1)检查当前处于忙碌状态的线程是否达到了设定的最大值m_MaxNum,如果达到了,表明目前没有空闲线程可用,而且也不能创建新的线程,因此必须等待直到有线程执行完毕返回到空闲队列中。 (2)如果当前的空闲线程数目小于我们设定的最小的空闲数目m_AvailLow,则我们必须创建新的线程,默认情况下,创建后的线程数目应该为m_InitNum,因此创建的线程数目应该为( 当前空闲线程数与m_InitNum);但是有一种特殊情况必须考虑,就是现有的线程总数加上创建后的线程数可能超过m_MaxNum,因此我们必须对线程的创建区别对待。 if(GetAllNum()+m_InitNum-m_IdleList.size() < m_MaxNum ) CreateIdleThread(m_InitNum-m_IdleList.size()); else CreateIdleThread(m_MaxNum-GetAllNum()); 如果创建后总数不超过m_MaxNum,则创建后的线程为m_InitNum;如果超过了,则只创建( m_MaxNum-当前线程总数 )个。 (3)调用GetIdleThread方法查找空闲线程。如果当前没有空闲线程,则挂起;否则将任务指派给该线程,同时将其移入忙碌队列。 当线程执行完毕后,其会调用MoveToIdleList方法移入空闲链表中,其中还调用m_IdleCond.Signal()方法,唤醒GetIdleThread()中可能阻塞的线程。 CWorkerThread CWorkerThread是CThread的派生类,是事实上的工作线程。在CThreadPool的构造函数中,我们创建了一定数量的CWorkerThread。一旦这些线程创建完毕,我们将调用Start()启动该线程。Start方法最终会调用Run方法。Run方法是个无限循环的过程。在没有接受到实际的任务的时候,m_Job为NULL,此时线程将调用Wait方 法进行等待,从而处于挂起状态。一旦线程池将具体的任务分发给该线程,其将被唤醒,从而通知线程从挂起的地方继续执行。CWorkerThread的完整定义如下: class CWorkerThread:public CThread { private: CThreadPool* m_ThreadPool; CJob* m_Job; void* m_JobData; CThreadMutex m_VarMutex; bool m_IsEnd; protected: public: CCondition m_JobCond; CThreadMutex m_WorkMutex; CWorkerThread(); virtual ~CWorkerThread(); void Run(); void SetJob(CJob* job,void* jobdata); CJob* GetJob(void){return m_Job;} void SetThreadPool(CThreadPool* thrpool); CThreadPool* GetThreadPool(void){return m_ThreadPool;} }; CWorkerThread::CWorkerThread() { m_Job = NULL; m_JobData = NULL; m_ThreadPool = NULL; m_IsEnd = false; } CWorkerThread::~CWorkerThread() { if(NULL != m_Job) delete m_Job; if(m_ThreadPool != NULL) } void CWorkerThread::Run() { SetThreadState(THREAD_RUNNING); for(;;) { m_Job->Run(m_JobData); m_Job->SetWorkThread(NULL); m_Job = NULL; m_ThreadPool->MoveToIdleList(this); while(m_Job == NULL) m_JobCond.Wait(); delete m_ThreadPool; if(m_ThreadPool->m_IdleList.size() > m_ThreadPool->GetAvailHighNum()) { m_ThreadPool->DeleteIdleThread(m_ThreadPool->m_IdleList.size()-m_T hreadPool->GetInitNum()); } m_WorkMutex.Unlock(); } } void CWorkerThread::SetJob(CJob* job,void* jobdata) { m_VarMutex.Lock(); m_Job = job; m_JobData = jobdata; job->SetWorkThread(this); m_VarMutex.Unlock(); m_JobCond.Signal(); } void CWorkerThread::SetThreadPool(CThreadPool* thrpool) { m_VarMutex.Lock(); m_ThreadPool = thrpool; m_VarMutex.Unlock(); } 搜索“diyifanwen.net”或“第一范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,第一范文网,提供最新教学研究Linux下通用线程池的创建与使用 (4)全文阅读和word下载服务。
相关推荐: