马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程池。下面是一个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之后,仅将当前正在执行的任务完成之后就会退出,我们也可以修改代码使得线程池在执行完任务链表中所有任务后再退出。
|