您的位置:首页 > 编程语言 > C语言/C++

C语言实现简单线程池

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

感谢作者Neover提供,转自http://www.cnblogs.com/newth/archive/2012/05/09/2492459.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: