之前在很多博客中看到一个关于线程池的实现代码,完全一致,于是产生了一点兴趣,于是将代码进行了编译,吓死,全是错误,于是,进行了修改,并运行通过。
(1)用户程序向任务队列中添加任务。
(2)创建线程池,线程睡眠,处于空闲状态。
(3)唤醒线程,线程池中的线程执行函数取出任务队列中的任务。
(4)执行任务中的调用函数,完成工作。
(5)线程池任务执行完判断,如果没有程序调用,线程继续睡眠。
(6)调用销毁函数对线程池进行销毁。
头文件pool.h如下。其中CThread_Worker为封装的任务,存放在链表上,等待线程执行该任务中的函数process,而CThread_pool是封装的线程池结构,线程池在创建的时候,会初始化该结构。pool_init()函数为线程池初始化。thread_routine()函数为线程的执行函数。myprocess()函数为任务执行的内容。函数pool_add_worker()的功能为将任务添加到等待队列上。poll_destroy()的功能为摧毁线程池,释放一切资源。
1 #ifndef _POOL_H
2 #define _POOL_H
3
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <sys/types.h>
8 #include <pthread.h>
9 #include <assert.h>
10 /*
11 *线程池所有运行和等待的任务都是一个CThread_Worker
12 *由于所有任务都在链表里,所以是一个链表结构
13 */
14 typedef struct worker{
15 /*回调函数,在任务运行时调用此函数*/
16 void *(*process)(void *arg);
17 void *arg;/*回调函数的参数*/
18 struct worker *next;
19 }CThread_Worker;
20
21 /*线程池结构*/
22 typedef struct{
23 pthread_mutex_t queue_lock;
24 pthread_cond_t queue_ready;
25
26 /*链表结构*/
27 CThread_Worker *queue_head;
28
29 /*是否摧毁线程池*/
30 int shutdown;
31 pthread_t *threadid;
32
33 /*线程池中允许活动线程的数量*/
34 int max_thread_num;
35
36 /*当前等待队列的任务数量*/
37 int cur_queue_size;
38 }CThread_Pool;
39
40 extern void pool_init(int max_thread_num);
41 extern void *thread_routine(void *arg);
42 extern void *myprocess(void *arg);
43 extern int pool_add_worker(void *(*process)(void *arg), void *arg);
44 extern int pool_destroy();
45 #endif
线程的核心代码threadpool.c内容如下,实现线程池操作函数的功能。
1 #include "pool.h"
2
3 static CThread_Pool *pool = NULL;
4 void *thread_routine(void *arg){
5 printf("thread start 0x%x\n", pthread_self());
6
7 while(1){
8 pthread_mutex_lock(&(pool->queue_lock));
9
10 /*如果等待队列为0并且不摧毁线程池,则线程处于阻塞状态*/
11 while(pool->cur_queue_size == 0 && !pool->shutdown){
12 printf("thread 0x%x is waiting\n", pthread_self());
13 pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
14 }
15
16 /*线程池如果摧毁*/
17 if(pool->shutdown){
18 pthread_mutex_unlock(&(pool->queue_lock));
19 printf("thread 0x%x will exit\n", pthread_self());
20 pthread_exit(NULL);
21 }
22
23 printf("thread 0x%x is starting to work\n", pthread_self());
24
25 assert(pool->cur_queue_size != 0);
26 assert(pool->queue_head != NULL);
27
28 /*等待队列长度减1,并取出链表中的头元素*/
29 pool->cur_queue_size--;
30 CThread_Worker *worker = pool->queue_head;
31 pool->queue_head = worker->next;
32
33 pthread_mutex_unlock(&(pool->queue_lock));
34
35 /*调用回调函数,执行任务*/
36 (*(worker->process))(worker->arg);
37
38 free(worker);
39 worker = NULL;
40 }
41 pthread_exit(NULL);
42 }
43 void pool_init(int max_thread_num){
44 pool = (CThread_Pool *)malloc(sizeof(CThread_Pool));
45
46 pthread_mutex_init(&(pool->queue_lock), NULL);
47 pthread_cond_init(&(pool->queue_ready), NULL);
48
49 pool->queue_head = NULL;
50
51 pool->max_thread_num = max_thread_num;
52 pool->cur_queue_size = 0;
53
54 pool->shutdown = 0;
55
56 pool->threadid =
(pthread_t *)malloc(max_thread_num * sizeof(pthread_t));
57
58 int i = 0;
59 for(i = 0; i < max_thread_num; i++){
60 pthread_create(&(pool->threadid[i]),
NULL, thread_routine, NULL);
61 }
62 }
63 /*测试代码,添加到线程池的任务*/
64 void *myprocess(void *arg){
65 printf("threadid is 0x%x, working on task %d\n",
pthread_self(), *(int *)arg);
66 sleep(1);
67 return NULL;
68 }
69 /*向线程池中添加任务*/
70 int pool_add_worker(void *(*process)(void *arg), void *arg){
71 /*构造一个新任务*/
72 CThread_Worker *newworker =
(CThread_Worker *)malloc(sizeof(CThread_Worker));
73 newworker->process = process;
74 newworker->arg = arg;
75 newworker->next = NULL;
76
77 pthread_mutex_lock(&(pool->queue_lock));
78
79 /*把任务放到等待队列中*/
80 CThread_Worker *member = pool->queue_head;
81 if(member != NULL){
82 while(member->next != NULL){
83 member = member->next;
84 }
85 member->next = newworker;
86 }
87 else{
88 pool->queue_head = newworker;
89 }
90
91 assert(pool->queue_head != NULL);
92
93 pool->cur_queue_size++;
94
95 pthread_mutex_unlock(&(pool->queue_lock));
96
97 /*等待队列中有任务,唤醒一个等待线程*/
98 pthread_cond_signal(&(pool->queue_ready));
99
100 }
101
102 /*
103 *摧毁线程池,等待队列中的任务不会再被执行,
104 *但是正在运行的线程会一直把任务运行完后再退出
105 */
106 int pool_destroy(){
107 if(pool->shutdown){
108 return -1;
109 }
110 pool->shutdown = 1;
111
112 /*唤醒所有等待的线程,线程池要摧毁了*/
113 pthread_cond_broadcast(&(pool->queue_ready));
114
115 /*阻塞等待线程退出,否则就成为僵尸进程了*/
116 int i;
117 for(i = 0; i<pool->max_thread_num; i++){
118 pthread_join(pool->threadid[i], NULL);
119 }
120 free(pool->threadid);
121
122 /*销毁等待队列*/
123 CThread_Worker *head = NULL;
124 while(pool->queue_head != NULL){
125 head = pool->queue_head;
126 pool->queue_head = pool->queue_head->next;
127 free(head);
128 }
129
130 pthread_mutex_destroy(&(pool->queue_lock));
131 pthread_cond_destroy(&(pool->queue_ready));
132
133 free(pool);
134 pool = NULL;
135
136 return 0;
137 }
测试代码main.c内容如下。
1 #include "pool.h"
2
3 int main(int argc, const char *argv[])
4 {
5 /*线程池中最多三个活动线程*/
6 pool_init(3);
7
8 sleep(1);
9 /*连续向池中投入10个任务*/
10 int *workingnum = (int *)malloc(sizeof(int) * 10);
11
12 int i;
13 for(i = 0; i < 10; i++){
14 workingnum[i] = i;
15 pool_add_worker(myprocess, &workingnum[i]);
16 }
17
18 sleep(5);
19
20 /*摧毁线程池*/
21 pool_destroy();
22 free(workingnum);
23 return 0;
24 }
工程管理器Makefile,示例如下。
1 .PHONY: all clean
2
3 all: test
4
5 test: main.o threadpool.o
6 gcc $^ -o $@ -lpthread
7
8 %.o:%.c
9 gcc -c $^ -o $@
10
11 clean:
12 rm -rf *.o test