该线程池的通用性高的多,因为它使用一个工作队列完全解除了主线程和工作线程之间的耦合关系:
主线程网工作队列中插入任务,工作线程通过竞争来取得任务并执行它。
不过,如果要将该线程池应用到实际服务器程序中,那么我们必须保证所有客户请求都是无状态的,因为同一个连接上的不同请求可能会由不同的线程处理。
示例代码如下,代码中的locker.h引自多线程编程 - 线程同步机制
#ifndef THREADPOOL_H#define THREADPOOL_H#include #include #include #include #include "locker.h"/*线程池类,将它定义为模板类是为了代码复用。模板参数T是任务类*/template class threadpool{public: /*参数thread_number是线程池中线程的数量, max_request是请求队列中最多允许的、等待处理的请求的数量*/ threadpool(int thread_number = 8, 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; /*描述线程池的数组,其大小为m_thread_number*/ std::list m_workqueue; /*请求队列*/ locker m_queuelocker; /*保护请求队列的互斥锁*/ sem m_queuestat; /*是否有任务需要处理*/ bool m_stop; /*是否结束线程*/};templatethreadpool::threadpool(int thread_number, int max_requests): m_thread_number(thread_number), m_max_requests(max_requests), m_stop(false), m_threads(NULL){ if(thread_number <= 0 || max_requests <= 0){ throw std::exception(); } m_threads = new pthread_t[m_thread_number]; if(!m_threads){ throw std::exception(); } /*创建thread_numbers个个数,并将它们都设置为脱离线程*/ 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])){ delete[] m_threads; throw std::exception(); } }}templatethreadpool::~threadpool(){ delete [] m_threads; m_stop = true;}templatebool threadpool::append(T* request){ /*操作工作队列时一定要加锁,因为它被所有线程共享*/ m_queuelocker.lock(); if(m_workqueue.size > m_max_requests){ m_queuelocker.unlock(); return false; } m_workqueue.push_back(request); m_queuelocker.unlock(); m_queuestat.post(); return true;}templatevoid *threadpool::worker(void* arg){ threadpool * pool = (threadpool*)arg; pool->run(); return pool;}templatevoid threadpool::run(){ 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(); }}#endif
这里需要注意的是,在C++程序中使用pthread_create函数时,该函数的第三个参数必须指向一个静态函数。而要在一个静态函数中使用类的动态成员(包括成员函数和成员变量),则只能通过如下两种方式实现:
- 访问类的静态对象来调用。如果单例模式中。静态函数可以通过类的全局唯一实例来访问动态成员函数
- 将类的对象作为参数参数传递给该静态函数,然后在静态函数中应用这个对象,并调用其动态代码
上述代码中,使用的是第二种方式:将线程参数设置为this指针,然后在worker函数中获取该指针并调用其动态方法run。