线程池
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <pthread.h>
- #include <assert.h>
- /*
- *线程池里所有运行和等待的任务都是一个CThread_worker
- *由于所有任务都在链表里,所以是一个链表结构
- */
- typedef struct worker
- {
- /*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/
- void *(*process) (void *arg);
- void *arg;/*回调函数的参数*/
- struct worker *next;
- } CThread_worker;
- /*线程池结构*/
- typedef struct
- {
- pthread_mutex_t queue_lock;
- pthread_cond_t queue_ready;
- /*链表结构,线程池中所有等待任务*/
- CThread_worker *queue_head;
- /*是否销毁线程池*/
- int shutdown;
- pthread_t *threadid;
- /*线程池中允许的活动线程数目*/
- int max_thread_num;
- /*当前等待队列的任务数目*/
- int cur_queue_size;
- } CThread_pool; /*定义线程池*/
- int pool_add_worker (void *(*process) (void *arg), void *arg);
- void *thread_routine (void *arg); /*routine:程序*/
- static CThread_pool *pool = NULL; /*声明 pool为线程池指针*/
- void pool_init (int max_thread_num) /*线程池初始化*/
- {
- pool = (CThread_pool *) malloc (sizeof (CThread_pool));
- /*线程池pool,初始化互斥量*/
- pthread_mutex_init (&(pool->queue_lock), NULL);
- /*线程池pool,初始化条件变量*/
- pthread_cond_init (&(pool->queue_ready), NULL);
- /
- pool->queue_head = NULL; /*任务队列头*/
- pool->max_thread_num = max_thread_num; /*最大线程数*/
- pool->cur_queue_size = 0; /*当前任务数*/
- pool->shutdown = 0; /*是否销毁*/
- pool->threadid =
- (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); /*申请线程地址空间*/
- int i = 0;
- for (i = 0; i < max_thread_num; i++)
- { /*把线程全部创建出来*/
- pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL);
- }
- }
- /*向线程池中加入任务*/
- int
- pool_add_worker (void *(*process) (void *arg), void *arg) /*线程添加*/
- {
- /*构造一个新任务*/
- CThread_worker *newworker =
- (CThread_worker *) malloc (sizeof (CThread_worker)); /*将任务传递进来*/
- newworker->process = process; /*任务函数*/
- newworker->arg = arg; /*函数参数*/
- newworker->next = NULL;/*别忘置空*/
- pthread_mutex_lock (&(pool->queue_lock)); /*添加新任务时需要加锁,防止其他线程改变公用变量*/
- /*将任务加入到等待队列中*/
- CThread_worker *member = pool->queue_head; /*任务队列传入*/
- if (member != NULL) /*任务队列不为空*/
- {
- while (member->next != NULL) /*任务队列链表遍历到最后位置*/
- member = member->next;
- member->next = newworker; /*新任务添加到队列链表中*/
- }
- else /*任务队列为空*/
- {
- pool->queue_head = newworker; /*新任务添加到队首*/
- }
- assert (pool->queue_head != NULL); /*任务添加过程结束后,任务队列仍为空,报错*/
- pool->cur_queue_size++; /*池内当前任务数+1*/
- pthread_mutex_unlock (&(pool->queue_lock)); /*解锁*/
- pthread_cond_signal (&(pool->queue_ready));/*每次等待队列中有任务加入,都会试图唤醒一个等待线程;如果所有线程都在忙碌,这句没有任何作用*/
- return 0;
- }
- /*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直
- 把任务运行完后再退出*/
- int pool_destroy () /*线程池销毁*/
- {
- if (pool->shutdown)
- return -1;/*防止两次调用*/
- pool->shutdown = 1;
- /*唤醒所有等待线程,线程池要销毁了*/
- pthread_cond_broadcast (&(pool->queue_ready));
- /*阻塞等待线程退出,否则就成僵尸了*/
- int i;
- for (i = 0; i < pool->max_thread_num; i++)
- pthread_join (pool->threadid[i], NULL);
- free (pool->threadid); /*释放每一个线程空间*/
- /*销毁等待队列*/
- CThread_worker *head = NULL;
- while (pool->queue_head != NULL)
- {
- head = pool->queue_head;
- pool->queue_head = pool->queue_head->next;
- free (head); /*释放任务队列空间*/
- }
- /*条件变量和互斥量也别忘了销毁*/
- pthread_mutex_destroy(&(pool->queue_lock));
- pthread_cond_destroy(&(pool->queue_ready));
- free (pool); /*释放线程池空间*/
- /*销毁后指针置空是个好习惯*/
- pool=NULL;
- return 0;
- }
- void * thread_routine (void *arg) /*线程调用函数*/
- {
- printf ("starting thread 0x%x\n", pthread_self ());
- while (1)
- {
- pthread_mutex_lock (&(pool->queue_lock));
- /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意
- pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
- while (pool->cur_queue_size == 0 && !pool->shutdown)
- {
- printf ("thread 0x%x is waiting\n", pthread_self ());
- pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));/*如果暂时没有任务,阻塞在此处,等待唤醒,防止不停查询,浪费CPU*/
- }
- /*线程池要销毁了*/
- if (pool->shutdown)
- {
- /*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
- pthread_mutex_unlock (&(pool->queue_lock));
- printf ("thread 0x%x will exit\n", pthread_self ());
- pthread_exit (NULL);
- }
- printf ("thread 0x%x is starting to work\n", pthread_self ());
- /*assert是调试的好帮手*/
- assert (pool->cur_queue_size != 0);
- assert (pool->queue_head != NULL);
- /*等待队列长度减去1,并取出链表中的头元素*/
- pool->cur_queue_size--;
- CThread_worker *worker = pool->queue_head; /*每次执行的都是任务队列中第一个任务*/
- pool->queue_head = worker->next; /*任务队列头下移一个*/
- pthread_mutex_unlock (&(pool->queue_lock));
- /*调用回调函数,执行任务*/
- (*(worker->process)) (worker->arg); /*开始执行取出来的任务*/
- free (worker);
- worker = NULL;
- }
- /*这一句应该是不可达的*/
- pthread_exit (NULL);
- }
- void * myprocess (void *arg) /*任务线程*/
- {
- printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
- sleep (1);/*休息一秒,延长任务的执行时间*/
- return NULL;
- }
- int main (int argc, char **argv)
- {
- pool_init (3);/*线程池中最多三个活动线程*/
- /*连续向池中投入10个任务*/
- int *workingnum = (int *) malloc (sizeof (int) * 10); /*任务编号*/
- int i;
- for (i = 0; i < 10; i++)
- {
- workingnum[i] = i;
- pool_add_worker (myprocess, &workingnum[i]); /*任务添加进等待队列*/
- }
- /*等待所有任务完成*/
- sleep (5);
- /*销毁线程池*/
- pool_destroy ();
- free (workingnum);
- return 0;
[root@localhost code]# ./thread_pool
starting thread 0xb63bab70
thread 0xb63bab70 is starting to work
threadid is 0xb63bab70, working on task 0
starting thread 0xb6dbbb70
thread 0xb6dbbb70 is starting to work
threadid is 0xb6dbbb70, working on task 1
starting thread 0xb77bcb70
thread 0xb77bcb70 is starting to work
threadid is 0xb77bcb70, working on task 2
thread 0xb63bab70 is starting to work
threadid is 0xb63bab70, working on task 3
thread 0xb6dbbb70 is starting to work
threadid is 0xb6dbbb70, working on task 4
thread 0xb77bcb70 is starting to work
threadid is 0xb77bcb70, working on task 5
thread 0xb63bab70 is starting to work
threadid is 0xb63bab70, working on task 6
thread 0xb6dbbb70 is starting to work
threadid is 0xb6dbbb70, working on task 7
thread 0xb77bcb70 is starting to work
threadid is 0xb77bcb70, working on task 8
thread 0xb63bab70 is starting to work
threadid is 0xb63bab70, working on task 9
thread 0xb6dbbb70 is waiting
thread 0xb77bcb70 is waiting
thread 0xb63bab70 is waiting
thread 0xb6dbbb70 will exit
thread 0xb77bcb70 will exit
thread 0xb63bab70 will exit[root@localhost code]#