C语言编写线程池的简单实现方法

本文介绍了一个使用C语言实现的简单线程池,通过创建固定数量的工作线程来处理任务,有效地减少了线程创建和销毁带来的开销,并提供了线程池的创建、销毁以及添加任务等功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

好文章,一起分享——


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

头文件:

 1: #ifndef THREAD_POOL_H__
 2: #define THREAD_POOL_H__
 3: 
 4: #include <pthread.h>
 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 <unistd.h>
 2: #include <stdlib.h>
 3: #include <errno.h>
 4: #include <string.h>
 5: #include <stdio.h>
 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 <unistd.h>
 2: #include <stdio.h>
 3: #include <stdlib.h>
 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://my.oschina.net/Bruce370/blog/391823

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值