Linux——线程 池
发布时间:2022-11-21 12:49:39 所属栏目:Linux 来源:
导读: 目录
一.概念
线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。
为什么要有线程池?
如果每次都只创建一个线程,首先当用户请求过多时,每次
一.概念
线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。
为什么要有线程池?
如果每次都只创建一个线程,首先当用户请求过多时,每次
|
目录 一.概念 线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。 为什么要有线程池? 如果每次都只创建一个线程,首先当用户请求过多时,每次都需要创建一个线程,创建线程需要时间和调度开销,这样会影响缓存的局部性和整体的性能。其次线程池linux,如果无上限一直创建线程,还会导致CPU的过分调度。 线程池已经创建好了一定数量的线程,等待着分配任务,这样避免了处理任务时的线程创建和销毁。线程池里线程个数确定,能够保证内核的充分利用,还能防止过分调度。 线程池中可用线程数量取决于可用额并发处理器,处理器内核,内存,网络socket等的数量。 线程池的应用场景: 需要大量的线程来完成任务,且完成人物的时间比较短。比如:WEB服务器完成网页请求这样的任务,因为当个任务小,并且任务量巨大,你可以想象一个热门网站的请求次数。但是对于长时间的任务,线程池的优先就不明显了。比如:一个Telnet连接请求,因为Telnet会话时间比线程创建时间大多了。对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。接收突发性的大量请求,但是不至于使服务器因此产生大量线程应用。突发性大量客户请求,在没有线程池的情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量的线程可能使内存到达极限,出现错误。二.线程池实现 线程池实际也是一个生产者消费者模型,接收任务,往任务队列中放任务的是生产者,从任务队列中拿任务并执行的是消费者。 主线程是生产者,用来接收任务和放任务。 int main(){ mythreadpool *tp=new mythreadpool(); tp->threadinit(); int count=10; while(1){ //sleep(1); int x=rand()+1; int y=rand()%20+1; Task t(x,y); //put里有加锁,不需要加锁了 tp->Put(t); std::cout<<"put Task done..."<ThreadQuit(); delete tp; return 0; } 线程池中的线程的创建封装在类中,线程获得任务的函数就会成为类的成员函数,在C++中,类的成员函数会隐含一个this指针,导致函数有两个参数,但是只能由一个参数,所以要对线程获得任务的函数加一个static,并且需要将调用对象的this指针作为参数传进来,不然就不能调用其它成员函数。 //成员函数,由this指针作为参数, //线程函数,只能有一个参数,所以要加static static void *handler(void *arg){ mythreadpool *p_this = (mythreadpool *)arg; while(1){ p_this->ThreadLock(); //不退出,没有数据要等待 while(!(p_this->_quit)&&(p_this->IsEmpty())){ p_this->ThreadWait(); } //退出没有数据,直接退出 //退出有数据,还需要执行任务 if(p_this->_quit&&p_this->IsEmpty()){ p_this->ThreadUnlock(); p_this->ThreadExit(); } //执行任务 Task t; p_this->Get(t); p_this->ThreadUnlock(); int res=0; res = t.Add(); std::cout< 注意如果服务还在运行,线程不退出,生产者不能有等待的情况,如果生产者等待,用户链接不上了。 线程退出: 设置一个标志位quit,起始设置false,不退出。当需要退出时将quit设置为true。 此时可能会有线程在等待,需要全部唤醒线程。 当线程还没有完全退出时,需要生产者等待。 当还有任务时,需要线程继续执行任务,执行完任务后才能退出。 总代码: #pragma once #include #include #include #include #define NUM 5 struct Task{ Task(){}; Task(int x, int y){ _x=x; _y=y; } ~Task(){}; int _x; int _y; int Add(){ return _x + _y; } }; class mythreadpool{ private: void ThreadLock(){ pthread_mutex_lock(&_lock); } void ThreadUnlock(){ pthread_mutex_unlock(&_lock); } void ThreadWait(){ pthread_cond_wait(&_cond, &_lock); } void ProductorWait(){ pthread_cond_wait(&_pcond, &_lock); } void ProductorSignal(){ pthread_cond_signal(&_pcond); } void ThreadSignal(){ pthread_cond_signal(&_cond); } //唤醒全部线程 void ThreadSignalAll(){ pthread_cond_broadcast(&_cond); } bool IsEmpty(){ return _q.empty(); } //退出线程 void ThreadExit(){ _numthread--; printf("%lu is exit\n",pthread_self()); ProductorSignal(); pthread_exit(0); } public: mythreadpool(size_t num = NUM) :_numthread(num) ,_quit(false) {} //成员函数,由this指针作为参数, //线程函数,只能有一个参数,所以要加static static void *handler(void *arg){ mythreadpool *p_this = (mythreadpool *)arg; while(1){ p_this->ThreadLock(); //不退出,没有数据要等待 while(!(p_this->_quit)&&(p_this->IsEmpty())){ p_this->ThreadWait(); } //退出没有数据,直接退出 //退出有数据,还需要执行任务 if(p_this->_quit&&p_this->IsEmpty()){ p_this->ThreadUnlock(); p_this->ThreadExit(); } //执行任务 Task t; p_this->Get(t); p_this->ThreadUnlock(); int res=0; res = t.Add(); std::cout< _q;//任务队列 size_t _numthread;//线程个数 pthread_mutex_t _lock;//锁 pthread_cond_t _cond;//消费者在此等待 pthread_cond_t _pcond;//生产者在此等待 bool _quit;//是否退出 }; #include"mythreadpool.hpp" int main(){ mythreadpool *tp=new mythreadpool(); tp->threadinit(); int count=10; while(1){ //sleep(1); int x=rand()+1; int y=rand()%20+1; Task t(x,y); //put里有加锁,不需要加锁了 tp->Put(t); std::cout<<"put Task done..."<ThreadQuit(); delete tp; return 0; } (编辑:拼字网 - 核心网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐

