简易线程池的实现
1 线程池
为了避免多线程操作过程种线程频繁申请和释放所带来的性能消耗,可以提前创建多个线程,当有任务到来时从线程池中选择一个线程执行,执行完后继续在线程池中待命。
核心是使用一个工作队列,主线程往工作队列中添加工作,工作线程从队列中取出工作并执行。
对工作队列的操作就是经典的生产者—消费者模型,需要用到互斥锁和条件变量。
2 工作定义
通过函数指针指向执行函数。
typedef struct Task{ void (*func)(void* arg); void* arg; }Task;
3 线程池定义
使用 list 容器来存储工作,定义工作队列的最大数 m_max_requests 和 线程总数 m_max_threads。在对工作队列操作时需要用到互斥锁 m_mutex_pool,条件变量 m_notfull 和 m_notempty。
class ThreadPool{ public: ThreadPool(int m_max_threads, int m_max_requests); ~ThreadPool(); bool addWork(void(*func)(void*), void* arg); private: static void* worker(void* arg); void run(); private: std::list<Task*> m_workqueue; /*工作队列*/ int m_max_requests; /*请求队列中允许的最大请求数*/ int m_max_threads; /*线程总数*/ pthread_t* m_worker_threads; /*工作线程*/ pthread_mutex_t m_mutex_pool; pthread_cond_t m_notfull; pthread_cond_t m_notempty; bool m_stop; }; ThreadPool::ThreadPool(int m_max_threads, int m_max_requests): m_max_threads(m_max_threads), m_max_requests(m_max_requests), m_stop(false){ if(m_max_threads <= 0 || m_max_requests <= 0){ throw std::exception(); } /*创建线程池*/ m_worker_threads = new pthread_t[m_max_threads]; if(!m_worker_threads){ throw std::exception(); } //memset(m_worker_threads, 0, sizeof(m_worker_threads)); /*初始化互斥锁、条件变量*/ if(0 != pthread_mutex_init(&m_mutex_pool, NULL) || 0 != pthread_cond_init(&m_notfull, NULL) || 0 != pthread_cond_init(&m_notempty, NULL)){ throw std::exception(); } /*创建工作线程*/ for(int i=0; i<m_max_threads; ++i){ printf("Create the %dth thread\n", i); if(0 != pthread_create(&m_worker_threads[i], 0, worker, this)){ delete []m_worker_threads; throw std::exception(); }; if(pthread_detach(m_worker_threads[i])){ delete [] m_worker_threads; throw std::exception(); } } } ThreadPool::~ThreadPool(){ delete []m_worker_threads; m_stop = true; } bool ThreadPool::addWork(void(*func)(void*), void* arg){ pthread_mutex_lock(&m_mutex_pool); while(!m_stop && m_workqueue.size() >= m_max_requests){ pthread_cond_wait(&m_notfull, &m_mutex_pool); } if(m_stop){ pthread_mutex_unlock(&m_mutex_pool); return false; } /*添加工作*/ Task* task = new Task; task->func = func; task->arg = arg; m_workqueue.push_back(task); pthread_mutex_unlock(&m_mutex_pool); pthread_cond_signal(&m_notempty); return true; } void* ThreadPool::worker(void* arg){ ThreadPool* pool = (ThreadPool*)arg; pool->run(); return pool; } void ThreadPool::run(){ while(1){ pthread_mutex_lock(&m_mutex_pool); while(m_workqueue.empty() && !m_stop){ pthread_cond_wait(&m_notempty, &m_mutex_pool); } /*从工作队列中取任务*/ Task* task = m_workqueue.front(); m_workqueue.pop_front(); pthread_mutex_unlock(&m_mutex_pool); pthread_cond_signal(&m_notfull); printf("Thread %ld start working...\n", pthread_self()); /*执行任务*/ task->func(task->arg); delete task; printf("Thread %ld end working...\n", pthread_self()); } } #endif
4 测试代码
#include "threadpool.h" #include<iostream> #include<unistd.h> using namespace std; void taskFunc(void* arg) { int num = *(int*)arg; printf("Thread %ld is working, number = %d\n", pthread_self(), num); sleep(1); } int main(){ ThreadPool* pool = new ThreadPool(10, 20); for (int i = 0; i < 100; ++i) { int* num = (int*)malloc(sizeof(int)); *num = i; pool->addWork(taskFunc, num); } sleep(30); return 0; }
References:
- 手写线程池 - C 语言版
- 《Linux高性能服务器编程》