成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

線程池原理詳解及如何用C語言實現線程池

網絡 通信技術
線程池是一種多線程處理形式,大多用于高并發服務器上,它能合理有效的利用高并發服務器上的線程資源;線程與進程用于處理各項分支子功能,我們通常的操作是:接收消息 ==> 消息分類 ==> 線程創建 ==> 傳遞消息到子線程 ==> 線程分離 ==> 在子線程中執行任務 ==> 任務結束退出。

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

[[317565]]

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

因此,線程池技術應運而生;線程池允許一個線程可以多次復用,且每次復用的線程內部的消息處理可以不相同,將創建與銷毀的開銷省去而不必來一個請求開一個線程;

結構講解:

線程池是一個抽象的概念,其內部由任務隊列,一堆線程,管理者線程組成;

線程池原理詳解及如何用C語言實現線程池

我們將以上圖為例,實現一個最基礎的線程池,接下來將分部分依次講解;講解順序為:1.線程池總體結構 2.線程數組 3.任務隊列 4.管理者線程 5.使用線程池接口的例子

一、線程池總體結構

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

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

線程池狀態信息:描述當前線程池的基本信息,如是否開啟、最小線程數、最大線程數、存活線程數、忙線程數、待銷毀線程數等… …

任務隊列信息:描述當前任務隊列基本信息,如最大任務數、隊列不為滿條件變量、隊列不為空條件變量等… …

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

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

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

  1. /*任務*/ 
  2. typedef struct { 
  3. void *(*function)(void *); 
  4. void *arg; 
  5. } threadpool_task_t; 
  6. /*線程池管理*/ 
  7. struct threadpool_t{ 
  8. pthread_mutex_t lock; /* 鎖住整個結構體 */ 
  9. pthread_mutex_t thread_counter; /* 用于使用忙線程數時的鎖 */ 
  10. pthread_cond_t queue_not_full; /* 條件變量,任務隊列不為滿 */ 
  11. pthread_cond_t queue_not_empty; /* 任務隊列不為空 */ 
  12. pthread_t *threads; /* 存放線程的tid,實際上就是管理了線 數組 */ 
  13. pthread_t admin_tid; /* 管理者線程tid */ 
  14. threadpool_task_t *task_queue; /* 任務隊列 */ 
  15. /*線程池信息*/ 
  16. int min_thr_num; /* 線程池中最小線程數 */ 
  17. int max_thr_num; /* 線程池中最大線程數 */ 
  18. int live_thr_num; /* 線程池中存活的線程數 */ 
  19. int busy_thr_num; /* 忙線程,正在工作的線程 */ 
  20. int wait_exit_thr_num; /* 需要銷毀的線程數 */ 
  21. /*任務隊列信息*/ 
  22. int queue_front; /* 隊頭 */ 
  23. int queue_rear; /* 隊尾 */ 
  24. int queue_size; 
  25. /* 存在的任務數 */ 
  26. int queue_max_size; /* 隊列能容納的最大任務數 */ 
  27. /*線程池狀態*/ 
  28. int shutdown; /* true為關閉 */ 
  29. }; 
  30. **/*創建線程池*/** 
  31. threadpool_t * 
  32. threadpool_create(int min_thr_num, int max_thr_num, int queue_max_size) 
  33. { /* 最小線程數 最大線程數 最大任務數*/ 
  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. /* 根據最大線程數,給工作線程數組開空間,清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指向當前線程池 threadpool_thread函數在后面講解 */ 
  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函數在后面講解 */ 
  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

二、線程數組

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

線程池原理詳解及如何用C語言實現線程池
  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. /* 無任務則阻塞在 “任務隊列不為空” 上,有任務則跳出 */ 
  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. /* 判斷線程池中的線程數是否大于最小線程數,是則結束當前線程 */ 
  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);//結束線程 
  21. /* 線程池開關狀態 */ 
  22. if (pool->shutdown) //關閉線程池 
  23. pthread_mutex_unlock(&(pool->lock)); 
  24. printf("thread 0x%x is exiting \n", (unsigned int)pthread_self()); 
  25. pthread_exit(NULL); //線程自己結束自己 
  26. //否則該線程可以拿出任務 
  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; //環型結構 
  30. pool->queue_size--; 
  31. //通知可以添加新任務 
  32. pthread_cond_broadcast(&(pool->queue_not_full)); 
  33. //釋放線程鎖 
  34. pthread_mutex_unlock(&(pool->lock)); 
  35. //執行剛才取出的任務 
  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); //執行任務 
  41. //任務結束處理 
  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); 

三、任務隊列

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

線程池原理詳解及如何用C語言實現線程池
  1. /*向線程池的任務隊列中添加一個任務*/ 
  2. int 
  3. threadpool_add_task(threadpool_t *pool, void *(*function)(void *arg), void *arg) 
  4. pthread_mutex_lock(&(pool->lock)); 
  5. /*如果隊列滿了,調用wait阻塞*/ 
  6. while ((pool->queue_size == pool->queue_max_size) && (!pool->shutdown)) 
  7. pthread_cond_wait(&(pool->queue_not_full), &(pool->lock)); 
  8. /*如果線程池處于關閉狀態*/ 
  9. if (pool->shutdown) 
  10. pthread_mutex_unlock(&(pool->lock)); 
  11. return -1; 
  12. /*清空工作線程的回調函數的參數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. /*添加任務到任務隊列*/ 
  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; /* 邏輯環 */ 
  20. pool->queue_size++; 
  21. /*添加完任務后,隊列就不為空了,喚醒線程池中的一個線程*/ 
  22. pthread_cond_signal(&(pool->queue_not_empty)); 
  23. pthread_mutex_unlock(&(pool->lock)); 
  24. return 0; 

四、管理者線程

作為線程池的管理者,該線程的主要功能包括:檢查線程池內線程的存活狀態,工作狀態;負責根據服務器當前的請求狀態去動態的增加或刪除線程,保證線程池中的線程數量維持在一個合理高效的平衡上;

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

  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; /*任務數*/ 
  11. int live_thr_num = pool->live_thr_num; /*存活的線程數*/ 
  12. pthread_mutex_unlock(&(pool->lock)); /*解鎖*/ 
  13. pthread_mutex_lock(&(pool->thread_counter)); 
  14. int busy_thr_num = pool->busy_thr_num; /*忙線程數*/ 
  15. pthread_mutex_unlock(&(pool->thread_counter)); 
  16. printf("admin busy live -%d--%d-\n", busy_thr_num, live_thr_num); 
  17. /*創建新線程 實際任務數量大于 最小正在等待的任務數量,存活線程數小于最大線程數*/ 
  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 都小于 存活線程,并且存活的大于最小線程數*/ 
  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); //發送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. //通知所有線程去自殺(在自己領任務的過程中) 
  29. for (i=0; i<pool->live_thr_num; i++) 
  30. pthread_cond_broadcast(&(pool->queue_not_empty)); 
  31. /*等待線程結束 先是pthread_exit 然后等待其結束*/ 
  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. /* 接收到任務后添加 */ 
  5. threadpool_add_task(thp, do_work, (void *)p); 
  6. // ... ... 
  7. /* 銷毀 */ 
  8. threadpool_destroy(thp); 

 

 

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2012-05-15 02:18:31

Java線程池

2020-12-10 08:24:40

線程池線程方法

2021-12-28 15:10:01

線程池C語言編程語言

2024-07-15 08:20:24

2024-11-21 07:00:00

線程池Java開發

2021-09-11 07:32:15

Java線程線程池

2018-10-31 15:54:47

Java線程池源碼

2023-05-19 08:01:24

Key消費場景

2023-08-02 08:03:08

Python線程池

2024-05-06 11:19:20

內存池計算機編程

2012-02-01 11:20:23

Java線程

2022-11-09 09:01:08

并發編程線程池

2023-11-29 16:38:12

線程池阻塞隊列開發

2021-05-26 11:30:24

Java線程池代碼

2024-11-13 16:37:00

Java線程池

2022-09-26 00:48:14

線程池阻塞數據

2024-09-09 15:09:30

2009-07-22 09:39:18

CLR線程池

2011-08-30 12:51:19

MySQL線程緩沖池

2025-02-24 00:00:10

.NET線程池模型
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国产精品一区 | 男插女下体视频 | 亚洲视频在线播放 | 欧美激情精品久久久久久 | 狠狠干天天干 | 久久久爽爽爽美女图片 | 久久成人国产 | 人人看人人干 | 久久精品小视频 | 日本成人区 | 国产欧美日韩视频 | 精品国产久 | 日韩精品一区二区三区视频播放 | 亚洲精品国产电影 | www.9191.com| 亚洲精品在线免费观看视频 | 国产中文字幕在线观看 | 色一情一乱一伦一区二区三区 | 亚洲网站在线播放 | 国产女人精品视频 | 国产在线激情视频 | 国产日韩一区二区 | 精品不卡 | 日日噜噜噜夜夜爽爽狠狠视频97 | 色婷婷av一区二区三区软件 | 久久久天堂 | 国产亚洲黄色片 | 免费在线看黄视频 | 中文字幕在线一区二区三区 | 国产乱码精品一区二区三区忘忧草 | 久久久精 | 国产免费观看一区 | 免费人成在线观看网站 | 成人免费一区二区三区牛牛 | 中文字幕久久精品 | 精品视频久久久 | 成人自拍视频 | 亚洲精选一区 | 在线观看中文字幕 | 国产精品美女久久久久久免费 | 亚洲精品一区二区三区在线 |