加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_宿迁站长网 (https://www.0527zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux 通用线程池的实现

发布时间:2022-11-16 18:34:16 所属栏目:Linux 来源:网络
导读: 用百度搜索一下“Linux线程池”,很出现很多个结果,有的提供的源程序是可以使用的,但仔细分析后,发现其设计结构的并不太合理。线程池的设计有两个难点。1、在池中线程完成一个任务后自动

用百度搜索一下“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的实现代码过长,受篇幅限制不便于发表,如有需要可以留言。

(编辑:云计算网_宿迁站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!