一个Linux下C线程池的实现(转)

什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。

下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。
pool_init()函数预先创建好max_thread_num个线程,每个线程执thread_routine ()函数。该函数中
  1. while (pool->cur_queue_size == 0)
  2. {
  3. ?????? pthread_cond_wait (&(pool->queue_ready),&(pool->queue_lock));
  4. }
表示如果任务链表中没有任务,则该线程出于阻塞等待状态。否则从队列中取出任务并执行。

pool_add_worker()函数向线程池的任务链表中加入一个任务,加入后通过调用pthread_cond_signal (&(pool->queue_ready))唤醒一个出于阻塞状态的线程(如果有的话)。

pool_destroy ()函数用于销毁线程池,线程池任务链表中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出。

下面贴出完整代码
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <pthread.h>
  6. #include <assert.h>

  7. typedef struct worker
  8. {
  9. ????
  10. ????void *(*process) (void *arg);
  11. ????void *arg;
  12. ????struct worker *next;

  13. } CThread_worker;


  14. typedef struct
  15. {
  16. ???? pthread_mutex_t queue_lock;
  17. ???? pthread_cond_t queue_ready;

  18. ????
  19. ???? CThread_worker *queue_head;

  20. ????
  21. ????int shutdown;
  22. ???? pthread_t *threadid;
  23. ????
  24. ????int max_thread_num;
  25. ????
  26. ????int cur_queue_size;

  27. } CThread_pool;


  28. int pool_add_worker (void *(*process) (void *arg), void *arg);
  29. void *thread_routine (void *arg);


  30. static CThread_pool *pool = NULL;
  31. void
  32. pool_init (int max_thread_num)
  33. {
  34. ???? pool = (CThread_pool *) malloc (sizeof (CThread_pool));

  35. ???? pthread_mutex_init (&(pool->queue_lock), NULL);
  36. ???? pthread_cond_init (&(pool->queue_ready), NULL);

  37. ???? pool->queue_head = NULL;

  38. ???? pool->max_thread_num = max_thread_num;
  39. ???? pool->cur_queue_size = 0;

  40. ???? pool->shutdown = 0;

  41. ???? pool->threadid =
  42. ???????? (pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
  43. ????int i = 0;
  44. ????for (i = 0; i < max_thread_num; i++)
  45. ???? {
  46. ???????? pthread_create (&(pool->threadid[i]), NULL, thread_routine,
  47. ???????????????? NULL);
  48. ???? }
  49. }


  50. int
  51. pool_add_worker (void *(*process) (void *arg), void *arg)
  52. {
  53. ????
  54. ???? CThread_worker *newworker =
  55. ???????? (CThread_worker *) malloc (sizeof (CThread_worker));
  56. ???? newworker->process = process;
  57. ???? newworker->arg = arg;
  58. ???? newworker->next = NULL;

  59. ???? pthread_mutex_lock (&(pool->queue_lock));
  60. ????
  61. ???? CThread_worker *member = pool->queue_head;
  62. ????if (member != NULL)
  63. ???? {
  64. ????????while (member->next != NULL)
  65. ???????????? member = member->next;
  66. ???????? member->next = newworker;
  67. ???? }
  68. ????else
  69. ???? {
  70. ???????? pool->queue_head = newworker;
  71. ???? }

  72. ???? assert (pool->queue_head != NULL);

  73. ???? pool->cur_queue_size++;
  74. ???? pthread_mutex_unlock (&(pool->queue_lock));
  75. ????
  76. ???? pthread_cond_signal (&(pool->queue_ready));
  77. ????return 0;
  78. }


  79. int
  80. pool_destroy ()
  81. {
  82. ????if (pool->shutdown)
  83. ????????return -1;
  84. ???? pool->shutdown = 1;

  85. ????
  86. ???? pthread_cond_broadcast (&(pool->queue_ready));

  87. ????
  88. ????int i;
  89. ????for (i = 0; i < pool->max_thread_num; i++)
  90. ???????? pthread_join (pool->threadid[i], NULL);
  91. ???? free (pool->threadid);

  92. ????
  93. ???? CThread_worker *head = NULL;
  94. ????while (pool->queue_head != NULL)
  95. ???? {
  96. ???????? head = pool->queue_head;
  97. ???????? pool->queue_head = pool->queue_head->next;
  98. ???????? free (head);
  99. ???? }
  100. ????
  101. ???? pthread_mutex_destroy(&(pool->queue_lock));
  102. ???? pthread_cond_destroy(&(pool->queue_ready));
  103. ????
  104. ???? free (pool);
  105. ????
  106. ???? pool=NULL;
  107. ????return 0;
  108. }


  109. void *
  110. thread_routine (void *arg)
  111. {
  112. ???? printf ("starting thread 0x%x\n", pthread_self ());
  113. ????while (1)
  114. ???? {
  115. ???????? pthread_mutex_lock (&(pool->queue_lock));
  116. ????????
  117. ????????while (pool->cur_queue_size == 0 && !pool->shutdown)
  118. ???????? {
  119. ???????????? printf ("thread 0x%x is waiting\n", pthread_self ());
  120. ???????????? pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
  121. ???????? }

  122. ????????
  123. ????????if (pool->shutdown)
  124. ???????? {
  125. ????????????
  126. ???????????? pthread_mutex_unlock (&(pool->queue_lock));
  127. ???????????? printf ("thread 0x%x will exit\n", pthread_self ());
  128. ???????????? pthread_exit (NULL);
  129. ???????? }

  130. ???????? printf ("thread 0x%x is starting to work\n", pthread_self ());

  131. ????????
  132. ???????? assert (pool->cur_queue_size != 0);
  133. ???????? assert (pool->queue_head != NULL);
  134. ????????
  135. ????????
  136. ???????? pool->cur_queue_size--;
  137. ???????? CThread_worker *worker = pool->queue_head;
  138. ???????? pool->queue_head = worker->next;
  139. ???????? pthread_mutex_unlock (&(pool->queue_lock));

  140. ????????
  141. ???????? (*(worker->process)) (worker->arg);
  142. ???????? free (worker);
  143. ???????? worker = NULL;
  144. ???? }
  145. ????
  146. ???? pthread_exit (NULL);
  147. }

??? 下面是测试代码
  1. void *
  2. myprocess (void *arg)
  3. {
  4. ???? printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
  5. ???? sleep (1);
  6. ????return NULL;
  7. }

  8. int
  9. main (int argc, char **argv)
  10. {
  11. ???? pool_init (3);
  12. ????
  13. ????
  14. ????int *workingnum = (int *) malloc (sizeof (int) * 10);
  15. ????int i;
  16. ????for (i = 0; i < 10; i++)
  17. ???? {
  18. ???????? workingnum[i] = i;
  19. ???????? pool_add_worker (myprocess, &workingnum[i]);
  20. ???? }
  21. ????
  22. ???? sleep (5);
  23. ????
  24. ???? pool_destroy ();

  25. ???? free (workingnum);
  26. ????return 0;
  27. }
将上述所有代码放入threadpool.c文件中,
在Linux输入编译命令
$ gcc -o threadpool threadpool.c -lpthread

以下是运行结果
starting thread 0xb7df6b90
thread 0xb7df6b90 is waiting
starting thread 0xb75f5b90
thread 0xb75f5b90 is waiting
starting thread 0xb6df4b90
thread 0xb6df4b90 is waiting
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 0
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 1
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 2
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 3
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 4
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 5
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 6
thread 0xb75f5b90 is starting to work
threadid is 0xb75f5b90, working on task 7
thread 0xb6df4b90 is starting to work
threadid is 0xb6df4b90, working on task 8
thread 0xb7df6b90 is starting to work
threadid is 0xb7df6b90, working on task 9
thread 0xb75f5b90 is waiting
thread 0xb6df4b90 is waiting
thread 0xb7df6b90 is waiting
thread 0xb75f5b90 will exit
thread 0xb6df4b90 will exit
thread 0xb7df6b90 will exit
<script type="text/javascript" id="wumiiRelatedItems"> </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值