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