线程池
Posted wangkaia
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池相关的知识,希望对你有一定的参考价值。
线程池:
一个线程池主要由以下的四个部分构成。
1 线程池管理器,负责创建线程和销毁线程,向工作队列中添加任务等。
2 工作线程,线程池当中负责执行任务的线程,当任务队列为空的情况下,则该线程处于等待的状态。
一般使用信号量来跟踪当先任务队列当中任务的数量,线程处于sem_wait()的状态,等待任务队列为非空
时,竞争的区执行任务。
3 任务接口,任务队列里面的任务都应该实现任务的接口,供工作线程调度执行,最主要的作用就是规
定了任务的入口。
4 任务队列,所有待执行的任务放在任务队列当中,提供了一种缓冲的机制。值得注意的是对任务队列
进行操作时一定要进行加锁。
下面来详细解释一个线程池的创建实例:
第一部分为线程池管理器,负责线程的创建和工作队列当中任务的添加,代码如下:
template<typename T> class threadpool{ public: threadpool(int thread_number,int max_requests=10000); ~threadpool(); //往队列里面添加任务 bool append(T* request); private: static void* worker(void* arg);//工作线程运行的函数,不断从队列当中取出任务,并执行该任务 void run(); private: int m_thread_number;//线程池里面的线程数目 int m_max_requests;//请求队列当中允许的最大请求数 pthread_t* m_threads;//描述线程池的数组 std::list<T*> m_workqueue;//请求队列 locker m_queuelocker;//保护请求队列的互斥锁 sem m_queuestat;//当前是否有任务需要处理 bool m_stop;//是否结束当前的线程 };
以上的thread_number用于初始化该线程池创建的线程数,max_requests用来管理该线程池所能接受的最大任务数。
将其创建为模板类,方便该线程池能够处理各种任务。其中用locker来保护任务队列,该locker里面封装的是pthread_mu
tex_t,sem里面封装的是sem_t用来体现任务对了里面的任务数目,并且用于线程之间使用竞争的方式来取得任务。
该class的构造函数如下:
template<typename T> threadpool<T>::threadpool(int thread_number,int max_requests):m_thread_number(thread_number),m_max_requests(max_requests), m_threads(NULL),m_stop(false) { if(thread_number)<1||max_requests<1) throw std::exception(); //创建存储线程号的数组 m_threads = new pthread_t[m_thread_number]; if(!m_threads) throw std::exception(); //创建规定个数的线程,并将线程设置为detach() for(int i=0;i<thread_number;i++) { printf("create the %dth thread ",i); if(pthread_create(m_threads+i,NULL,worker,this)!=0) { delete []m_threads; throw std::exception(); } if(pthread_detach(m_threads[i])) { //分离成功的话,则返回值为0 delete []m_threads; throw std::exception; } } }
在c++里面使用pthread_create()函数时,传入的第三个参数务必要是静态函数,本次的构造函数将
线程池对象本身作为参数传递给了工作线程。其作为第二部分的代码如下:
template<typename T> void* threadpool<T>::worker(void* arg){ //工作线程的参数为空指针的类型 threadpool* pool=(threadpool*)arg; pool->run(); return pool; } //工作线程执行的函数 template<typename T> void threadpool<T>::run() { //m_stop全局对象用来保证,当线程执行完一个任务队列当中的任务之后仍然能够继续从 while(!m_stop) { //等待当前的对立面有任务 m_queuestat.wait(); //加锁后读取并执行队列里面的任务 m_queuelocker.lock(); if(m_workqueue.empty()){ m_queuelocker.unlock(); continue; } T* request=m_workqueue.front(); m_workqueue.pop_front(); m_queuelocker.unlock(); if(!request) continue; request->process(); } }
工作线程,从任务队列当中取出任务,并执行。全局变量m_stop保证了工作线程在对象销毁
之前会一直不断的从任务队列当中取出任务并执行。
本次的线程池没有针对具体的任务形式,因此没有涉及任务接口的涉及,等以后补充。
以上是关于线程池的主要内容,如果未能解决你的问题,请参考以下文章