自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

線程池原理詳解及如何用C語言實(shí)現(xiàn)線程池

網(wǎng)絡(luò) 通信技術(shù)
線程池是一種多線程處理形式,大多用于高并發(fā)服務(wù)器上,它能合理有效的利用高并發(fā)服務(wù)器上的線程資源;線程與進(jìn)程用于處理各項(xiàng)分支子功能,我們通常的操作是:接收消息 ==> 消息分類 ==> 線程創(chuàng)建 ==> 傳遞消息到子線程 ==> 線程分離 ==> 在子線程中執(zhí)行任務(wù) ==> 任務(wù)結(jié)束退出。

 線程池是一種多線程處理形式,大多用于高并發(fā)服務(wù)器上,它能合理有效的利用高并發(fā)服務(wù)器上的線程資源;線程與進(jìn)程用于處理各項(xiàng)分支子功能,我們通常的操作是:接收消息 ==> 消息分類 ==> 線程創(chuàng)建 ==> 傳遞消息到子線程 ==> 線程分離 ==> 在子線程中執(zhí)行任務(wù) ==> 任務(wù)結(jié)束退出;

[[317565]]

對大多數(shù)小型局域網(wǎng)的通信來說,上述方法足夠滿足需求;但當(dāng)我們的通信范圍擴(kuò)大到廣域網(wǎng)或大型局域網(wǎng)通信中時,我們將面臨大量消息頻繁請求服務(wù)器;在這種情況下,創(chuàng)建與銷毀線程都已經(jīng)成為一種奢侈的開銷,特別對于嵌入式服務(wù)器來說更應(yīng)保證內(nèi)存資源的合理利用;

因此,線程池技術(shù)應(yīng)運(yùn)而生;線程池允許一個線程可以多次復(fù)用,且每次復(fù)用的線程內(nèi)部的消息處理可以不相同,將創(chuàng)建與銷毀的開銷省去而不必來一個請求開一個線程;

結(jié)構(gòu)講解:

線程池是一個抽象的概念,其內(nèi)部由任務(wù)隊列,一堆線程,管理者線程組成;

線程池原理詳解及如何用C語言實(shí)現(xiàn)線程池

我們將以上圖為例,實(shí)現(xiàn)一個最基礎(chǔ)的線程池,接下來將分部分依次講解;講解順序?yàn)椋?.線程池總體結(jié)構(gòu) 2.線程數(shù)組 3.任務(wù)隊列 4.管理者線程 5.使用線程池接口的例子

一、線程池總體結(jié)構(gòu)

這里講解線程池在邏輯上的結(jié)構(gòu)體;看下方代碼,該結(jié)構(gòu)體threadpool_t中包含線程池狀態(tài)信息,任務(wù)隊列信息以及多線程操作中的互斥鎖;在任務(wù)結(jié)構(gòu)體中包含了一個可以放置多種不同任務(wù)函數(shù)的函數(shù)指針,一個傳入該任務(wù)函數(shù)的void*類型的參數(shù);

注意:在使用時需要將你的消息分類處理函數(shù)裝入任務(wù)的(*function);然后放置到任務(wù)隊列并通知空閑線程;

線程池狀態(tài)信息:描述當(dāng)前線程池的基本信息,如是否開啟、最小線程數(shù)、最大線程數(shù)、存活線程數(shù)、忙線程數(shù)、待銷毀線程數(shù)等… …

任務(wù)隊列信息:描述當(dāng)前任務(wù)隊列基本信息,如最大任務(wù)數(shù)、隊列不為滿條件變量、隊列不為空條件變量等… …

多線程互斥鎖:保證在同一時間點(diǎn)上只有一個線程在任務(wù)隊列中取任務(wù)并修改任務(wù)隊列信息、修改線程池信息;

函數(shù)指針:在打包消息階段,將分類后的消息處理函數(shù)放在(*function);

void*類型參數(shù):用于傳遞消息處理函數(shù)需要的信息;

  1. /*任務(wù)*/ 
  2. typedef struct { 
  3. void *(*function)(void *); 
  4. void *arg; 
  5. } threadpool_task_t; 
  6. /*線程池管理*/ 
  7. struct threadpool_t{ 
  8. pthread_mutex_t lock; /* 鎖住整個結(jié)構(gòu)體 */ 
  9. pthread_mutex_t thread_counter; /* 用于使用忙線程數(shù)時的鎖 */ 
  10. pthread_cond_t queue_not_full; /* 條件變量,任務(wù)隊列不為滿 */ 
  11. pthread_cond_t queue_not_empty; /* 任務(wù)隊列不為空 */ 
  12. pthread_t *threads; /* 存放線程的tid,實(shí)際上就是管理了線 數(shù)組 */ 
  13. pthread_t admin_tid; /* 管理者線程tid */ 
  14. threadpool_task_t *task_queue; /* 任務(wù)隊列 */ 
  15. /*線程池信息*/ 
  16. int min_thr_num; /* 線程池中最小線程數(shù) */ 
  17. int max_thr_num; /* 線程池中最大線程數(shù) */ 
  18. int live_thr_num; /* 線程池中存活的線程數(shù) */ 
  19. int busy_thr_num; /* 忙線程,正在工作的線程 */ 
  20. int wait_exit_thr_num; /* 需要銷毀的線程數(shù) */ 
  21. /*任務(wù)隊列信息*/ 
  22. int queue_front; /* 隊頭 */ 
  23. int queue_rear; /* 隊尾 */ 
  24. int queue_size; 
  25. /* 存在的任務(wù)數(shù) */ 
  26. int queue_max_size; /* 隊列能容納的最大任務(wù)數(shù) */ 
  27. /*線程池狀態(tài)*/ 
  28. int shutdown; /* true為關(guān)閉 */ 
  29. }; 
  30. **/*創(chuàng)建線程池*/** 
  31. threadpool_t * 
  32. threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size) 
  33. { /* 最小線程數(shù) 最大線程數(shù) 最大任務(wù)數(shù)*/ 
  34. int i; 
  35. threadpool_t *pool = NULL
  36. do 
  37. /* 線程池空間開辟 */ 
  38. if ((pool=(threadpool_t *)malloc(sizeof(threadpool_t))) == NULL
  39. printf("malloc threadpool false; \n"); 
  40. break; 
  41. /*信息初始化*/ 
  42. pool->min_thr_num = min_thr_num; 
  43. pool->max_thr_num = max_thr_num; 
  44. pool->busy_thr_num = 0; 
  45. pool->live_thr_num = min_thr_num; 
  46. pool->wait_exit_thr_num = 0; 
  47. pool->queue_front = 0; 
  48. pool->queue_rear = 0; 
  49. pool->queue_size = 0; 
  50. pool->queue_max_size = queue_max_size; 
  51. pool->shutdown = false
  52. /* 根據(jù)最大線程數(shù),給工作線程數(shù)組開空間,清0 */ 
  53. pool->threads = (pthread_t *)malloc(sizeof(pthread_t)*max_thr_num); 
  54. if (pool->threads == NULL
  55. printf("malloc threads false;\n"); 
  56. break; 
  57. memset(pool->threads, 0, sizeof(pthread_t)*max_thr_num); 
  58. /* 隊列開空間 */ 
  59. pool->task_queue = 
  60. (threadpool_task_t *)malloc(sizeof(threadpool_task_t)*queue_max_size); 
  61. if (pool->task_queue == NULL
  62. printf("malloc task queue false;\n"); 
  63. break; 
  64. /* 初始化互斥鎖和條件變量 */ 
  65. if ( pthread_mutex_init(&(pool->lock), NULL) != 0 || 
  66. pthread_mutex_init(&(pool->thread_counter), NULL) !=0 || 
  67. pthread_cond_init(&(pool->queue_not_empty), NULL) !=0 || 
  68. pthread_cond_init(&(pool->queue_not_full), NULL) !=0) 
  69. printf("init lock or cond false;\n"); 
  70. break; 
  71. /* 啟動min_thr_num個工作線程 */ 
  72. for (i=0; i<min_thr_num; i++) 
  73. /* pool指向當(dāng)前線程池 threadpool_thread函數(shù)在后面講解 */ 
  74. pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool); 
  75. printf("start thread 0x%x... \n", (unsigned int)pool->threads[i]); 
  76. /* 管理者線程 admin_thread函數(shù)在后面講解 */ 
  77. pthread_create(&(pool->admin_tid), NULL, admin_thread, (void *)pool); 
  78. return pool; 
  79. } while(0); 
  80. /* 釋放pool的空間 */ 
  81. threadpool_free(pool); 
  82. return NULL

二、線程數(shù)組

線程數(shù)組實(shí)際上是在線程池初始化時開辟的一段存放一堆線程tid的空間,在邏輯上形成一個池,里面放置著提前創(chuàng)建的線程;這段空間中包含了正在工作的線程,等待工作的線程(空閑線程),等待被銷毀的線程,申明但沒有初始化的線程空間;

線程池原理詳解及如何用C語言實(shí)現(xiàn)線程池
  1. /*工作線程*/ 
  2. void * 
  3. threadpool_thread(void *threadpool) 
  4. threadpool_t *pool = (threadpool_t *)threadpool; 
  5. threadpool_task_t task; 
  6. while (true
  7. pthread_mutex_lock(&(pool->lock)); 
  8. /* 無任務(wù)則阻塞在 “任務(wù)隊列不為空” 上,有任務(wù)則跳出 */ 
  9. while ((pool->queue_size == 0) && (!pool->shutdown)) 
  10. printf("thread 0x%x is waiting \n", (unsigned int)pthread_self()); 
  11. pthread_cond_wait(&(pool->queue_not_empty), &(pool->lock)); 
  12. /* 判斷是否需要清除線程,自殺功能 */ 
  13. if (pool->wait_exit_thr_num > 0) 
  14. pool->wait_exit_thr_num--; 
  15. /* 判斷線程池中的線程數(shù)是否大于最小線程數(shù),是則結(jié)束當(dāng)前線程 */ 
  16. if (pool->live_thr_num > pool->min_thr_num) 
  17. printf("thread 0x%x is exiting \n", (unsigned int)pthread_self()); 
  18. pool->live_thr_num--; 
  19. pthread_mutex_unlock(&(pool->lock)); 
  20. pthread_exit(NULL);//結(jié)束線程 
  21. /* 線程池開關(guān)狀態(tài) */ 
  22. if (pool->shutdown) //關(guān)閉線程池 
  23. pthread_mutex_unlock(&(pool->lock)); 
  24. printf("thread 0x%x is exiting \n", (unsigned int)pthread_self()); 
  25. pthread_exit(NULL); //線程自己結(jié)束自己 
  26. //否則該線程可以拿出任務(wù) 
  27. task.function = pool->task_queue[pool->queue_front].function; //出隊操作 
  28. task.arg = pool->task_queue[pool->queue_front].arg; 
  29. pool->queue_front = (pool->queue_front + 1) % pool->queue_max_size; //環(huán)型結(jié)構(gòu) 
  30. pool->queue_size--; 
  31. //通知可以添加新任務(wù) 
  32. pthread_cond_broadcast(&(pool->queue_not_full)); 
  33. //釋放線程鎖 
  34. pthread_mutex_unlock(&(pool->lock)); 
  35. //執(zhí)行剛才取出的任務(wù) 
  36. printf("thread 0x%x start working \n", (unsigned int)pthread_self()); 
  37. pthread_mutex_lock(&(pool->thread_counter)); //鎖住忙線程變量 
  38. pool->busy_thr_num++; 
  39. pthread_mutex_unlock(&(pool->thread_counter)); 
  40. (*(task.function))(task.arg); //執(zhí)行任務(wù) 
  41. //任務(wù)結(jié)束處理 
  42. printf("thread 0x%x end working \n", (unsigned int)pthread_self()); 
  43. pthread_mutex_lock(&(pool->thread_counter)); 
  44. pool->busy_thr_num--; 
  45. pthread_mutex_unlock(&(pool->thread_counter)); 
  46. pthread_exit(NULL); 

三、任務(wù)隊列

任務(wù)隊列的存在形式與線程數(shù)組相似;在線程池初始化時根據(jù)傳入的最大任務(wù)數(shù)開辟空間;當(dāng)服務(wù)器前方后請求到來后,分類并打包消息成為任務(wù),將任務(wù)放入任務(wù)隊列并通知空閑線程來取;不同之處在于任務(wù)隊列有明顯的先后順序,先進(jìn)先出;而線程數(shù)組中的線程則是一個競爭關(guān)系去拿到互斥鎖爭取任務(wù);

線程池原理詳解及如何用C語言實(shí)現(xiàn)線程池
  1. /*向線程池的任務(wù)隊列中添加一個任務(wù)*/ 
  2. int 
  3. threadpool_add_task(threadpool_t *pool, void *(*function)(void *arg), void *arg) 
  4. pthread_mutex_lock(&(pool->lock)); 
  5. /*如果隊列滿了,調(diào)用wait阻塞*/ 
  6. while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) 
  7. pthread_cond_wait(&(pool->queue_not_full), &(pool->lock)); 
  8. /*如果線程池處于關(guān)閉狀態(tài)*/ 
  9. if (pool->shutdown) 
  10. pthread_mutex_unlock(&(pool->lock)); 
  11. return -1; 
  12. /*清空工作線程的回調(diào)函數(shù)的參數(shù)arg*/ 
  13. if (pool->task_queue[pool->queue_rear].arg != NULL
  14. free(pool->task_queue[pool->queue_rear].arg); 
  15. pool->task_queue[pool->queue_rear].arg = NULL
  16. /*添加任務(wù)到任務(wù)隊列*/ 
  17. pool->task_queue[pool->queue_rear].function = function
  18. pool->task_queue[pool->queue_rear].arg = arg; 
  19. pool->queue_rear = (pool->queue_rear + 1) % pool->queue_max_size; /* 邏輯環(huán) */ 
  20. pool->queue_size++; 
  21. /*添加完任務(wù)后,隊列就不為空了,喚醒線程池中的一個線程*/ 
  22. pthread_cond_signal(&(pool->queue_not_empty)); 
  23. pthread_mutex_unlock(&(pool->lock)); 
  24. return 0; 

四、管理者線程

作為線程池的管理者,該線程的主要功能包括:檢查線程池內(nèi)線程的存活狀態(tài),工作狀態(tài);負(fù)責(zé)根據(jù)服務(wù)器當(dāng)前的請求狀態(tài)去動態(tài)的增加或刪除線程,保證線程池中的線程數(shù)量維持在一個合理高效的平衡上;

說到底,它就是一個單獨(dú)的線程,定時的去檢查,根據(jù)我們的一個維持平衡算法去增刪線程;

  1. /*管理線程*/ 
  2. void * 
  3. admin_thread(void *threadpool) 
  4. int i; 
  5. threadpool_t *pool = (threadpool_t *)threadpool; 
  6. while (!pool->shutdown) 
  7. printf("admin -----------------\n"); 
  8. sleep(DEFAULT_TIME); /*隔一段時間再管理*/ 
  9. pthread_mutex_lock(&(pool->lock)); /*加鎖*/ 
  10. int queue_size = pool->queue_size; /*任務(wù)數(shù)*/ 
  11. int live_thr_num = pool->live_thr_num; /*存活的線程數(shù)*/ 
  12. pthread_mutex_unlock(&(pool->lock)); /*解鎖*/ 
  13. pthread_mutex_lock(&(pool->thread_counter)); 
  14. int busy_thr_num = pool->busy_thr_num; /*忙線程數(shù)*/ 
  15. pthread_mutex_unlock(&(pool->thread_counter)); 
  16. printf("admin busy live -%d--%d-\n", busy_thr_num, live_thr_num); 
  17. /*創(chuàng)建新線程 實(shí)際任務(wù)數(shù)量大于 最小正在等待的任務(wù)數(shù)量,存活線程數(shù)小于最大線程數(shù)*/ 
  18. if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num <= pool->max_thr_num) 
  19. printf("admin add-----------\n"); 
  20. pthread_mutex_lock(&(pool->lock)); 
  21. int add=0; 
  22. /*一次增加 DEFAULT_THREAD_NUM 個線程*/ 
  23. for (i=0; i<pool->max_thr_num && add<DEFAULT_THREAD_NUM 
  24. && pool->live_thr_num < pool->max_thr_num; i++) 
  25. if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i])) 
  26. pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool); 
  27. add++; 
  28. pool->live_thr_num++; 
  29. printf("new thread -----------------------\n"); 
  30. pthread_mutex_unlock(&(pool->lock)); 
  31. /*銷毀多余的線程 忙線程x2 都小于 存活線程,并且存活的大于最小線程數(shù)*/ 
  32. if ((busy_thr_num*2) < live_thr_num && live_thr_num > pool->min_thr_num) 
  33. // printf("admin busy --%d--%d----\n", busy_thr_num, live_thr_num); 
  34. /*一次銷毀DEFAULT_THREAD_NUM個線程*/ 
  35. pthread_mutex_lock(&(pool->lock)); 
  36. pool->wait_exit_thr_num = DEFAULT_THREAD_NUM; 
  37. pthread_mutex_unlock(&(pool->lock)); 
  38. for (i=0; i<DEFAULT_THREAD_NUM; i++) 
  39. //通知正在處于空閑的線程,自殺 
  40. pthread_cond_signal(&(pool->queue_not_empty)); 
  41. printf("admin cler --\n"); 
  42. return NULL
  43. /*線程是否存活*/ 
  44. int 
  45. is_thread_alive(pthread_t tid) 
  46. int kill_rc = pthread_kill(tid, 0); //發(fā)送0號信號,測試是否存活 
  47. if (kill_rc == ESRCH) //線程不存在 
  48. return false
  49. return true

五、釋放

  1. /*釋放線程池*/ 
  2. int 
  3. threadpool_free(threadpool_t *pool) 
  4. if (pool == NULL
  5. return -1; 
  6. if (pool->task_queue) 
  7. free(pool->task_queue); 
  8. if (pool->threads) 
  9. free(pool->threads); 
  10. pthread_mutex_lock(&(pool->lock)); /*先鎖住再銷毀*/ 
  11. pthread_mutex_destroy(&(pool->lock)); 
  12. pthread_mutex_lock(&(pool->thread_counter)); 
  13. pthread_mutex_destroy(&(pool->thread_counter)); 
  14. pthread_cond_destroy(&(pool->queue_not_empty)); 
  15. pthread_cond_destroy(&(pool->queue_not_full)); 
  16. free(pool); 
  17. pool = NULL
  18. return 0; 
  19. /*銷毀線程池*/ 
  20. int 
  21. threadpool_destroy(threadpool_t *pool) 
  22. int i; 
  23. if (pool == NULL
  24. return -1; 
  25. pool->shutdown = true
  26. /*銷毀管理者線程*/ 
  27. pthread_join(pool->admin_tid, NULL); 
  28. //通知所有線程去自殺(在自己領(lǐng)任務(wù)的過程中) 
  29. for (i=0; i<pool->live_thr_num; i++) 
  30. pthread_cond_broadcast(&(pool->queue_not_empty)); 
  31. /*等待線程結(jié)束 先是pthread_exit 然后等待其結(jié)束*/ 
  32. for (i=0; i<pool->live_thr_num; i++) 
  33. pthread_join(pool->threads[i], NULL); 
  34. threadpool_free(pool); 
  35. return 0; 

六、接口

  1. /* 線程池初始化,其管理者線程及工作線程都會啟動 */ 
  2. threadpool_t *thp = threadpool_create(10, 100, 100); 
  3. printf("threadpool init ... ... \n"); 
  4. /* 接收到任務(wù)后添加 */ 
  5. threadpool_add_task(thp, do_work, (void *)p); 
  6. // ... ... 
  7. /* 銷毀 */ 
  8. threadpool_destroy(thp); 

 

 

責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2012-05-15 02:18:31

Java線程池

2020-12-10 08:24:40

線程池線程方法

2021-12-28 15:10:01

線程池C語言編程語言

2021-09-11 07:32:15

Java線程線程池

2024-11-21 07:00:00

線程池Java開發(fā)

2024-07-15 08:20:24

2018-10-31 15:54:47

Java線程池源碼

2023-05-19 08:01:24

Key消費(fèi)場景

2023-08-02 08:03:08

Python線程池

2022-11-09 09:01:08

并發(fā)編程線程池

2024-05-06 11:19:20

內(nèi)存池計算機(jī)編程

2012-02-01 11:20:23

Java線程

2023-11-29 16:38:12

線程池阻塞隊列開發(fā)

2021-05-26 11:30:24

Java線程池代碼

2024-09-09 15:09:30

2024-11-13 16:37:00

Java線程池

2022-09-26 00:48:14

線程池阻塞數(shù)據(jù)

2023-10-13 08:20:02

Spring線程池id

2021-07-16 11:35:20

Java線程池代碼

2009-07-22 09:39:18

CLR線程池
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號