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

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

http://www.linuxidc.com/Linux/2013-01/77619.htm

有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池。下面是一个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之后,仅将当前正在执行的任务完成之后就会退出,我们也可以修改代码使得线程池在执行完任务链表中所有任务后再退出。

转载地址:http://ahoii.baihongyu.com/

你可能感兴趣的文章
C++ 非类型模版参数
查看>>
设计模式 依赖倒转原则 & 里氏代换原则
查看>>
DirectX11 光照
查看>>
图形学 图形渲染管线
查看>>
DirectX11 计时和动画
查看>>
DirectX11 光照与材质的相互作用
查看>>
DirectX11 法线向量
查看>>
DirectX11 兰伯特余弦定理(Lambert)
查看>>
DirectX11 漫反射光
查看>>
DirectX11 环境光
查看>>
DirectX11 镜面光
查看>>
DirectX11 三种光照组成对比
查看>>
DirectX11 指定材质
查看>>
DirectX11 平行光
查看>>
DirectX11 点光
查看>>
DirectX11 聚光灯
查看>>
DirectX11 HLSL打包(packing)格式和“pad”变量的必要性
查看>>
DirectX11 光照演示示例Demo
查看>>
漫谈一下前端的可视化技术
查看>>
VUe+webpack构建单页router应用(一)
查看>>