<wbr><wbr><wbr>一些网络服务器在单位时间内需要处理大量的连接请求,但服务的时间去很短。使用普通的方法,即接收一个服务请求,创建一个服务线程方法来提供服务,会浪费系统很多资源。因为线程的创建和销毁己经占用了大量的CPU。而使用线程池方法能够很好的解决这一问题。</wbr></wbr></wbr>
<wbr><wbr><wbr>线程池采用预创建技术,在应用程序启动后,立即创建一定数量的线程,并让这些线程处于阻塞状态,(即空闲线程)不消耗CPU,只占用较小的内存空间。当任务来临时,应用程序即唤醒一个空闲的线程,并处理此任务。当此线程处理完任务后,重新回到阻塞状态,并不退出。当系统比较空闲时,大部分线程处于空闲状态,线程池会自动销毁一些线程,回收系统资源。</wbr></wbr></wbr>
<wbr><wbr><wbr>下面一个线程池构架。不同于一些网友对线程池的设计,此构架更为简单。程序是根据一网络上现有程序修改的,链接地址:<a target="_blank" href="http://cppthreadpool.googlecode.com/svn/trunk/">http://cppthreadpool.googlecode.com/svn/trunk/</a>,有兴趣的话可以自己去看源代码,在这里不做过多介绍。</wbr></wbr></wbr>
<wbr><wbr><wbr>线程池共有两个类,WorkThread 和 ThreadPool。WorkThread是工作线程类,即线程池中线程所需执行的任务。当有一个新的WorkerThread对象到达时,即有一个处于阻塞状态的线程被唤醒。</wbr></wbr></wbr>
class WorkerThread{
public:
<wbr><wbr><wbr> intid;</wbr></wbr></wbr>
<wbr><wbr><wbr>unsigned virtual executeThis()</wbr></wbr></wbr>
<wbr><wbr><wbr>{<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>return 0;<br><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>WorkerThread(int id) : id(id) {}<br><wbr><wbr><wbr> virtual~WorkerThread(){}<br> };</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>ThreadPool类负责对线程池进行管理,包括:创建新线程、线程间的同步、把新的任务加入到工作队列中、让池中的线程数动态的改变。其类声明如下:</wbr></wbr></wbr>
class ThreadPool{
public:
<wbr><wbr><wbr>ThreadPool();<br><wbr><wbr><wbr>ThreadPool(int maxThreadsTemp);<br><wbr><wbr><wbr> virtual~ThreadPool();</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>void destroyPool(int maxPollSecs);</wbr></wbr></wbr>
<wbr><wbr><wbr>bool assignWork(WorkerThread *worker);<br><wbr><wbr><wbr> boolfetchWork(WorkerThread **worker);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>void initializeThreads();<br><wbr><br><wbr><wbr><wbr> static void*threadExecute(void *param);</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>static pthread_mutex_t mutexSync;<br><wbr><wbr><wbr> staticpthread_mutex_t mutexWorkCompletion;<br><wbr><wbr><wbr><br> protected:<br><wbr><wbr><wbr> staticvoid<wbr><wbr><wbr>MoveToBusyList(pthread_tid);<wbr><wbr><wbr>//moveand idle thread to busy thread<br><wbr><wbr><wbr> staticvoid<wbr><wbr><wbr>MoveToIdleList(pthread_t id);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr><wbr><wbr>void CreateIdleThread(int num);<br><wbr><wbr><wbr> voidDeleteIdleThread(int num);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr><wbr><wbr>pthread_mutex_tm_VarMutex;<wbr><wbr><wbr><wbr><wbr><wbr><wbr>//mutex for var</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>pthread_mutex_tmutexThreadList;<wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>static pthread_mutex_t mutexBusyList;<br><wbr><wbr><wbr> staticpthread_mutex_t mutexIdleList;</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
private:
<wbr><wbr><wbr> unsigned intm_InitNum;</wbr></wbr></wbr>
<wbr><wbr><wbr>unsigned int m_MaxNum;<br><wbr><wbr><wbr> unsigned intm_AvailLow;<br><wbr><wbr><wbr> unsigned intm_AvailHigh;<br><wbr><wbr><wbr> //unsignedint m_AvailNum;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr> sem_tavailableWork;<br><wbr><wbr><wbr> //sem_tavailableThreads;</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr><wbr><wbr>vector<pthread_t><wbr><wbr>m_ThreadList;<wbr>//ThreadList<wbr><br><wbr><wbr><wbr> staticvector<pthread_t><wbr><wbr>m_BusyList;<wbr><wbr>//BusyList</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>staticvector<pthread_t><wbr><wbr>m_IdleList;<wbr><wbr>//IdleList</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>vector<WorkerThread *>workerQueue;</wbr></wbr></wbr>
<wbr><wbr><wbr>//int topIndex;<br><wbr><wbr><wbr> //intbottomIndex;<br><wbr><br><wbr><wbr><wbr><wbr>intincompleteWork;<wbr><wbr><wbr>//number of works be done</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr><br><wbr><wbr><wbr> intqueueSize;<wbr><wbr><wbr><wbr>//thesize of workQueue</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
};
<wbr><wbr><wbr></wbr></wbr></wbr>在源程序上进行了适当的修改,使得池中的空闲线程数可以动态的变化。创建一个线程后,立即此线程的ID存入m_ThreadList 和 m_IdleList队列中,通过调用fetchWork函数将自己置于阻塞状态。当workerQueue中没有任务等待执行,fetchWork执行sem_wait()即处于阻塞状态。当有新的任务加入到workerQueue 中,availableWork 信号执行一次 sem_post操作,唤醒一个空闲线程。线程被唤醒后,其ID号被添加到 m_BusyList队列中,执行完任务后,ID号在 m_BusyList队列中被删除,再添加到 m_IdleList 队列中。
<wbr><wbr><wbr>应用程序所创建的线程总数不能超过m_MaxNum,池中的线程总数不高于m_MaxNum时,空闲线程维持在 m_AvailLow之上,同样,当空闲线程数高于m_AvailHigh时,程序会自动销毁一些线程,使空闲线程数目维持在一个合理的范围内。</wbr></wbr></wbr>
<wbr><wbr><wbr>调用的实现方法如下:</wbr></wbr></wbr>
int main(int argc, char **argv)
{
<wbr><wbr><wbr>ThreadPool* myPool = new ThreadPool(20);<br><wbr><wbr><wbr>myPool->initializeThreads();</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>//We will count time elapsed after initializeThreads()<br><wbr><wbr><wbr> time_tt1=time(NULL);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>//Lets start bullying ThreadPool with tonnes of work !!!<br><wbr><wbr><wbr> for(unsignedint i=0;i<ITERATIONS;i ){<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>SampleWorkerThread* myThread = new SampleWorkerThread(i);<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>cout << "myThread["<< myThread->id<< "] = ["<< myThread<< "]"<< endl;<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>myPool->assignWork(myThread);<br><wbr><wbr><wbr> }<br><wbr><br><wbr><wbr><wbr>sleep(10);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>for(unsigned int i=0;i<ITERATIONS;i ){<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>SampleWorkerThread* myThread = new SampleWorkerThread(i);<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>cout << "myThread["<< myThread->id<< "] = ["<< myThread<< "]"<< endl;<br><wbr><wbr><wbr><wbr><wbr><wbr><wbr>myPool->assignWork(myThread);<br><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>sleep(10);<br><wbr><wbr><wbr>myPool->destroyPool(2);</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>time_t t2=time(NULL);<br><wbr><wbr><wbr> cout<< t2-t1<< " seconds elapsed\n"<< endl;<br><wbr><wbr><wbr>deletemyPool;<br><wbr><br><wbr><wbr><wbr> return0;<br></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>}
<wbr><wbr><wbr>通过这个测试程序,我们可以看到池中的线程数动态的变化。</wbr></wbr></wbr>
<wbr></wbr>
<wbr><wbr><wbr>ThreadPool的实现代码过长,受篇幅限制不便于发表,如有需要可以留言。</wbr></wbr></wbr>
<wbr><wbr></wbr></wbr>