博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言实现简单线程池
阅读量:5067 次
发布时间:2019-06-12

本文共 6044 字,大约阅读时间需要 20 分钟。

有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池。下面是一个C语言实现的简单的线程池。

头文件:

1: #ifndef THREAD_POOL_H__
2: #define THREAD_POOL_H__
3: 
4: #include 
5: 
6: /* 要执行的任务链表 */
7: typedef struct tpool_work {
8:     void*               (*routine)(void*);       /* 任务函数 */
9:     void                *arg;                    /* 传入任务函数的参数 */
10:     struct tpool_work   *next;
11: }tpool_work_t;
12: 
13: typedef struct tpool {
14:     int             shutdown;                    /* 线程池是否销毁 */
15:     int             max_thr_num;                /* 最大线程数 */
16:     pthread_t       *thr_id;                    /* 线程ID数组 */
17:     tpool_work_t    *queue_head;                /* 线程链表 */
18:     pthread_mutex_t queue_lock;
19:     pthread_cond_t  queue_ready;
20: }tpool_t;
21: 
22: /*
23:  * @brief     创建线程池
24:  * @param     max_thr_num 最大线程数
25:  * @return     0: 成功 其他: 失败
26:  */
27: int
28: tpool_create(int max_thr_num);
29: 
30: /*
31:  * @brief     销毁线程池
32:  */
33: void
34: tpool_destroy();
35: 
36: /*
37:  * @brief     向线程池中添加任务
38:  * @param    routine 任务函数指针
39:  * @param     arg 任务函数参数
40:  * @return     0: 成功 其他:失败
41:  */
42: int
43: tpool_add_work(void*(*routine)(void*), void *arg);
44: 
45: #endif

实现:

1: #include 
2: #include 
3: #include 
4: #include 
5: #include 
6: 
7: #include "tpool.h"
8: 
9: static tpool_t *tpool = NULL;
10: 
11: /* 工作者线程函数, 从任务链表中取出任务并执行 */
12: static void*
13: thread_routine(void *arg)
14: {
15:     tpool_work_t *work;
16:
17:     while(1) {
18:         /* 如果线程池没有被销毁且没有任务要执行,则等待 */
19:         pthread_mutex_lock(&tpool->queue_lock);
20:         while(!tpool->queue_head && !tpool->shutdown) {
21:             pthread_cond_wait(&tpool->queue_ready, &tpool->queue_lock);
22:         }
23:         if (tpool->shutdown) {
24:             pthread_mutex_unlock(&tpool->queue_lock);
25:             pthread_exit(NULL);
26:         }
27:         work = tpool->queue_head;
28:         tpool->queue_head = tpool->queue_head->next;
29:         pthread_mutex_unlock(&tpool->queue_lock);
30: 
31:         work->routine(work->arg);
32:         free(work);
33:     }
34:
35:     return NULL;
36: }
37: 
38: /*
39:  * 创建线程池
40:  */
41: int
42: tpool_create(int max_thr_num)
43: {
44:     int i;
45: 
46:     tpool = calloc(1, sizeof(tpool_t));
47:     if (!tpool) {
48:         printf("%s: calloc failed\n", __FUNCTION__);
49:         exit(1);
50:     }
51:
52:     /* 初始化 */
53:     tpool->max_thr_num = max_thr_num;
54:     tpool->shutdown = 0;
55:     tpool->queue_head = NULL;
56:     if (pthread_mutex_init(&tpool->queue_lock, NULL) !=0) {
57:         printf("%s: pthread_mutex_init failed, errno:%d, error:%s\n",
58:             __FUNCTION__, errno, strerror(errno));
59:         exit(1);
60:     }
61:     if (pthread_cond_init(&tpool->queue_ready, NULL) !=0 ) {
62:         printf("%s: pthread_cond_init failed, errno:%d, error:%s\n",
63:             __FUNCTION__, errno, strerror(errno));
64:         exit(1);
65:     }
66:
67:     /* 创建工作者线程 */
68:     tpool->thr_id = calloc(max_thr_num, sizeof(pthread_t));
69:     if (!tpool->thr_id) {
70:         printf("%s: calloc failed\n", __FUNCTION__);
71:         exit(1);
72:     }
73:     for (i = 0; i < max_thr_num; ++i) {
74:         if (pthread_create(&tpool->thr_id[i], NULL, thread_routine, NULL) != 0){
75:             printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__,
76:                 errno, strerror(errno));
77:             exit(1);
78:         }
79:
80:     }
81: 
82:     return 0;
83: }
84: 
85: /* 销毁线程池 */
86: void
87: tpool_destroy()
88: {
89:     int i;
90:     tpool_work_t *member;
91: 
92:     if (tpool->shutdown) {
93:         return;
94:     }
95:     tpool->shutdown = 1;
96: 
97:     /* 通知所有正在等待的线程 */
98:     pthread_mutex_lock(&tpool->queue_lock);
99:     pthread_cond_broadcast(&tpool->queue_ready);
100:     pthread_mutex_unlock(&tpool->queue_lock);
101:     for (i = 0; i < tpool->max_thr_num; ++i) {
102:         pthread_join(tpool->thr_id[i], NULL);
103:     }
104:     free(tpool->thr_id);
105: 
106:     while(tpool->queue_head) {
107:         member = tpool->queue_head;
108:         tpool->queue_head = tpool->queue_head->next;
109:         free(member);
110:     }
111: 
112:     pthread_mutex_destroy(&tpool->queue_lock);
113:     pthread_cond_destroy(&tpool->queue_ready);
114: 
115:     free(tpool);
116: }
117: 
118: /* 向线程池添加任务 */
119: int
120: tpool_add_work(void*(*routine)(void*), void *arg)
121: {
122:     tpool_work_t *work, *member;
123:
124:     if (!routine){
125:         printf("%s:Invalid argument\n", __FUNCTION__);
126:         return -1;
127:     }
128:
129:     work = malloc(sizeof(tpool_work_t));
130:     if (!work) {
131:         printf("%s:malloc failed\n", __FUNCTION__);
132:         return -1;
133:     }
134:     work->routine = routine;
135:     work->arg = arg;
136:     work->next = NULL;
137: 
138:     pthread_mutex_lock(&tpool->queue_lock);
139:     member = tpool->queue_head;
140:     if (!member) {
141:         tpool->queue_head = work;
142:     } else {
143:         while(member->next) {
144:             member = member->next;
145:         }
146:         member->next = work;
147:     }
148:     /* 通知工作者线程,有新任务添加 */
149:     pthread_cond_signal(&tpool->queue_ready);
150:     pthread_mutex_unlock(&tpool->queue_lock);
151: 
152:     return 0;
153: }
154:
155: 

测试代码:

1: #include 
2: #include 
3: #include 
4: #include "tpool.h"
5: 
6: void *func(void *arg)
7: {
8:     printf("thread %d\n", (int)arg);
9:     return NULL;
10: }
11: 
12: int
13: main(int arg, char **argv)
14: {
15:     if (tpool_create(5) != 0) {
16:         printf("tpool_create failed\n");
17:         exit(1);
18:     }
19:
20:     int i;
21:     for (i = 0; i < 10; ++i) {
22:         tpool_add_work(func, (void*)i);
23:     }
24:     sleep(2);
25:     tpool_destroy();
26:     return 0;
27: }

这个实现是在调用tpool_destroy之后,仅将当前正在执行的任务完成之后就会退出,我们也可以修改代码使得线程池在执行完任务链表中所有任务后再退出。

转载于:https://www.cnblogs.com/newth/archive/2012/05/09/2492459.html

你可能感兴趣的文章
SQL with(unlock)与with(readpast) (转)
查看>>
什么是长尾理论
查看>>
html5-6 Frame框架窗口类型
查看>>
新东方雅思词汇---6.1、oppose
查看>>
DFS序
查看>>
js进阶ajax函数封装(匿名函数作为参数传递)(封装函数引入文件的方式非常好用)...
查看>>
tomcat服务器安装
查看>>
SQL中的long text
查看>>
jsp中<%! %>
查看>>
CSUOJ-1980 不堪重负的数(区间dp)
查看>>
你对博客中提到的评分规则有何意见和建议?
查看>>
Oracle-RAC安装随笔
查看>>
Linux下screen的应用
查看>>
第一百七十四节,jQuery,Ajax进阶
查看>>
linux解压war包的命令
查看>>
OpenStack从入门到放弃
查看>>
CentOS 配置软raid
查看>>
学习后缀数组笔记
查看>>
项目微管理18 - 嘴遁
查看>>
常用模板
查看>>