歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux管理 >> Linux網絡 >> Linux網絡編程:線程池的使用

Linux網絡編程:線程池的使用

日期:2017/3/1 10:30:35   编辑:Linux網絡

一、什麼是線程池

應用程序可以有多個線程,這些線程在休眠狀態中需要耗費大量時間來等待事件發生。其他線程可能進入睡眠狀態,並且僅定期被喚醒以輪循更改或更新狀態信息,然後再次進入休眠狀態。為了簡化對這些線程的管理,.NET框架為每個進程提供了一個線程池,一個線程池有若干個等待操作狀態,當一個等待操作完成時,線程池中的輔助線程會執行回調函數。線程池中的線程由系統管理,程序員不需要費力於線程管理,可以集中精力處理應用程序任務。

線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然後在創建線程後自動啟動這些任務。線程池線程都是後台線程.每個線程都使用默認的堆棧大小,以默認的優先級運行,並處於多線程單元中.如果某個線程在托管代碼中空閒(如正在等待某個事件),則線程池將插入另一個輔助線程來使所有處理器保持繁忙.如果所有線程池線程都始終保持繁忙,但隊列中包含掛起的工作,則線程池將在一段時間後創建另一個輔助線程但線程的數目永遠不會超過最大值.超過最大值的線程可以排隊,但他們要等到其他線程完成後才啟動

二、什麼情況下不要使用線程池

●如果需要使一個任務具有特定優先級

●如果具有可能會長時間運行(並因此阻塞其他任務)的任務

●如果需要將線程放置到單線程單元中(線程池中的線程均處於多線程單元中)

●如果需要永久標識來標識和控制線程,比如想使用專用線程來終止該線程,將其掛起或按名稱發現它


下面給出一個線程池的例子,以供大家參考:

[cpp]

  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. /*
  8. *線程池裡所有運行和等待的任務都是一個CThread_worker
  9. *由於所有任務都在鏈表裡,所以是一個鏈表結構
  10. */
  11. typedef struct worker
  12. {
  13. /*回調函數,任務運行時會調用此函數,注意也可聲明成其它形式*/
  14. void *(*process) (void *arg);
  15. void *arg;/*回調函數的參數*/
  16. struct worker *next;
  17. } CThread_worker;
  18. /*線程池結構*/
  19. typedef struct
  20. {
  21. pthread_mutex_t queue_lock;
  22. pthread_cond_t queue_ready;
  23. /*鏈表結構,線程池中所有等待任務*/
  24. CThread_worker *queue_head;
  25. /*是否銷毀線程池*/
  26. int shutdown;
  27. pthread_t *threadid;
  28. /*線程池中允許的活動線程數目*/
  29. int max_thread_num;
  30. /*當前等待隊列的任務數目*/
  31. int cur_queue_size;
  32. } CThread_pool;
  33. int pool_add_worker (void *(*process) (void *arg), void *arg);
  34. void *thread_routine (void *arg);
  35. static CThread_pool *pool = NULL;
  36. void pool_init (int max_thread_num)
  37. {
  38. pool = (CThread_pool *) malloc (sizeof (CThread_pool));
  39. pthread_mutex_init (&(pool->queue_lock), NULL);
  40. pthread_cond_init (&(pool->queue_ready), NULL);
  41. pool->queue_head = NULL;
  42. pool->max_thread_num = max_thread_num;
  43. pool->cur_queue_size = 0;
  44. pool->shutdown = 0;
  45. pool->threadid =
  46. (pthread_t *) malloc (max_thread_num * sizeof (pthread_t));
  47. int i = 0;
  48. for (i = 0; i < max_thread_num; i++)
  49. {
  50. pthread_create (&(pool->threadid[i]), NULL, thread_routine,
  51. NULL);
  52. }
  53. }
  54. /*向線程池中加入任務*/
  55. int
  56. pool_add_worker (void *(*process) (void *arg), void *arg)
  57. {
  58. /*構造一個新任務*/
  59. CThread_worker *newworker =
  60. (CThread_worker *) malloc (sizeof (CThread_worker));
  61. newworker->process = process;
  62. newworker->arg = arg;
  63. newworker->next = NULL;/*別忘置空*/
  64. pthread_mutex_lock (&(pool->queue_lock));
  65. /*將任務加入到等待隊列中*/
  66. CThread_worker *member = pool->queue_head;
  67. if (member != NULL)
  68. {
  69. while (member->next != NULL)
  70. member = member->next;
  71. member->next = newworker;
  72. }
  73. else
  74. {
  75. pool->queue_head = newworker;
  76. }
  77. assert (pool->queue_head != NULL);
  78. pool->cur_queue_size++;
  79. pthread_mutex_unlock (&(pool->queue_lock));
  80. /*好了,等待隊列中有任務了,喚醒一個等待線程;
  81. 注意如果所有線程都在忙碌,這句沒有任何作用*/
  82. pthread_cond_signal (&(pool->queue_ready));
  83. return 0;
  84. }
  85. /*銷毀線程池,等待隊列中的任務不會再被執行,但是正在運行的線程會一直
  86. 把任務運行完後再退出*/
  87. int pool_destroy ()
  88. {
  89. if (pool->shutdown)
  90. return -1;/*防止兩次調用*/
  91. pool->shutdown = 1;
  92. /*喚醒所有等待線程,線程池要銷毀了*/
  93. pthread_cond_broadcast (&(pool->queue_ready));
  94. /*阻塞等待線程退出,否則就成僵屍了*/
  95. int i;
  96. for (i = 0; i < pool->max_thread_num; i++)
  97. pthread_join (pool->threadid[i], NULL);
  98. free (pool->threadid);
  99. /*銷毀等待隊列*/
  100. CThread_worker *head = NULL;
  101. while (pool->queue_head != NULL)
  102. {
  103. head = pool->queue_head;
  104. pool->queue_head = pool->queue_head->next;
  105. free (head);
  106. }
  107. /*條件變量和互斥量也別忘了銷毀*/
  108. pthread_mutex_destroy(&(pool->queue_lock));
  109. pthread_cond_destroy(&(pool->queue_ready));
  110. free (pool);
  111. /*銷毀後指針置空是個好習慣*/
  112. pool=NULL;
  113. return 0;
  114. }
  115. void * thread_routine (void *arg)
  116. {
  117. printf ("starting thread 0x%x\n", pthread_self ());
  118. while (1)
  119. {
  120. pthread_mutex_lock (&(pool->queue_lock));
  121. /*如果等待隊列為0並且不銷毀線程池,則處於阻塞狀態; 注意
  122. pthread_cond_wait是一個原子操作,等待前會解鎖,喚醒後會加鎖*/
  123. while (pool->cur_queue_size == 0 && !pool->shutdown)
  124. {
  125. printf ("thread 0x%x is waiting\n", pthread_self ());
  126. pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
  127. }
  128. /*線程池要銷毀了*/
  129. if (pool->shutdown)
  130. {
  131. /*遇到break,continue,return等跳轉語句,千萬不要忘記先解鎖*/
  132. pthread_mutex_unlock (&(pool->queue_lock));
  133. printf ("thread 0x%x will exit\n", pthread_self ());
  134. pthread_exit (NULL);
  135. }
  136. printf ("thread 0x%x is starting to work\n", pthread_self ());
  137. /*assert是調試的好幫手*/
  138. assert (pool->cur_queue_size != 0);
  139. assert (pool->queue_head != NULL);
  140. /*等待隊列長度減去1,並取出鏈表中的頭元素*/
  141. pool->cur_queue_size--;
  142. CThread_worker *worker = pool->queue_head;
  143. pool->queue_head = worker->next;
  144. pthread_mutex_unlock (&(pool->queue_lock));
  145. /*調用回調函數,執行任務*/
  146. (*(worker->process)) (worker->arg);
  147. free (worker);
  148. worker = NULL;
  149. }
  150. /*這一句應該是不可達的*/
  151. pthread_exit (NULL);
  152. }
  153. void * myprocess (void *arg)
  154. {
  155. printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
  156. sleep (1);/*休息一秒,延長任務的執行時間*/
  157. return NULL;
  158. }
  159. int main (int argc, char **argv)
  160. {
  161. pool_init (3);/*線程池中最多三個活動線程*/
  162. /*連續向池中投入10個任務*/
  163. int *workingnum = (int *) malloc (sizeof (int) * 10);
  164. int i;
  165. for (i = 0; i < 10; i++)
  166. {
  167. workingnum[i] = i;
  168. pool_add_worker (myprocess, &workingnum[i]);
  169. }
  170. /*等待所有任務完成*/
  171. sleep (5);
  172. /*銷毀線程池*/
  173. pool_destroy ();
  174. free (workingnum);
  175. return 0;
  176. }
Copyright © Linux教程網 All Rights Reserved