想做一个多线程服务器测试程序,因此参考了github的一些实例,然后自己动手写了类似的代码来加深理解。
目前了解的线程池实现有2种思路:
第一种:
主进程创建一定数量的线程,并将其全部挂起,此时线程状态为idle,并将running态计数为0,等到任务可以执行了,就唤醒线程,此时线程状态为running,计数增加,如果计数达到最大线程数,就再创建一组空闲线程,等待新任务,上一组线程执行完退出,如此交替。
第二种:
采用生成者-消费者模式,主进程作为生成者,创建FIFO队列,在任务队列尾部添加任务,线程池作为消费者在队列头部取走任务执行,这之间有人会提到无锁环形队列,在单生成者单消费者的模式下是有效的,但是线程池肯定是多消费者同时去队列取任务,环形队列会造成挂死。
我的实例采用第二种方式实现,在某些应用场景下,允许一定时间内,任务排队的情况,重复利用已有线程会比较合适。
代码比较占篇幅,因此折叠在下面。
task.h:
1 #ifndef TASK_H 2 #define TASK_H 3 4 #include <list> 5 #include <pthread.h> 6 7 using std::list; 8 9 struct task { 10 void (*function) (void *); 11 void *arguments; 12 int id; 13 }; 14 15 struct work_queue { 16 work_queue(){ 17 pthread_mutex_init(&queue_lock, NULL); 18 pthread_mutex_init(&queue_read_lock, NULL); 19 pthread_cond_init(&queue_read_cond, NULL); 20 qlen = 0; 21 } 22 23 ~work_queue() { 24 queue.clear(); 25 pthread_mutex_destroy(&queue_read_lock); 26 pthread_mutex_destroy(&queue_lock); 27 pthread_cond_destroy(&queue_read_cond); 28 } 29 30 void push(task *tsk); 31 task *pull(); 32 void post(); 33 void wait(); 34 35 private: 36 int qlen; 37 list< task * > queue; 38 pthread_mutex_t queue_lock; 39 pthread_mutex_t queue_read_lock; 40 pthread_cond_t queue_read_cond; 41 }; 42 43 #endif