一個簡單的linux線程池

http://blog.csdn.net/wzjking0929/article/details/20312675

線程池:簡單地說,線程池 就是預先創建好一批線程,方便、快速地處理收到的業務。比起傳統的到來一個任務,即時創建一個線程來處理,節省了線程的創建和回收的開銷,響應更快,效率更高。

?

在linux中,使用的是posix線程庫,首先介紹幾個常用的函數:

1 線程的創建和取消函數

pthread_create

創建線程

pthread_join

合并線程

pthread_cancel

取消線程

2 線程同步函數

pthread_mutex_lock

pthread_mutex_unlock

pthread_cond_signal

pthread_cond_wait

?

關于函數的詳細說明,參考man手冊

?

線程池的實現:

線程池的實現主要分為三部分,線程的創建、添加任務到線程池中、工作線程從任務隊列中取出任務進行處理。

主要有兩個類來實現,CTask,CThreadPool

/**
執行任務的類,設置任務數據并執行
**/

C代碼??收藏代碼
  1. class?CTask??
  2. {??
  3. protected:??
  4. ?string?m_strTaskName;??//任務的名稱??
  5. ?void*?m_ptrData;???????//要執行的任務的具體數據??
  6. public:??
  7. ?CTask(){}??
  8. ?CTask(string?taskName)??
  9. ?{??
  10. ??this->m_strTaskName?=?taskName;??
  11. ??m_ptrData?=?NULL;??
  12. ?}??
  13. ?virtual?int?Run()=?0;??
  14. ?void?SetData(void*?data);????//設置任務數據??
  15. };??

?

任務類是個虛類,所有的任務要從CTask類中繼承 ,實現run接口,run接口中需要實現的就是具體解析任務的邏輯。m_ptrData是指向任務數據的指針,可以是簡單數據類型,也可以是自定義的復雜數據類型。

?

線程池類

/**
線程池
**/

Java代碼??收藏代碼
  1. class?CThreadPool??
  2. {??
  3. private:??
  4. ?vector<CTask*>?m_vecTaskList;?????????//任務列表??
  5. ?int?m_iThreadNum;????????????????????????????//線程池中啟動的線程數?????????????
  6. ?static?vector<pthread_t>?m_vecIdleThread;???//當前空閑的線程集合??
  7. ?static?vector<pthread_t>?m_vecBusyThread;???//當前正在執行的線程集合??
  8. ?static?pthread_mutex_t?m_pthreadMutex;????//線程同步鎖??
  9. ?static?pthread_cond_t?m_pthreadCond;????//線程同步的條件變量??
  10. protected:??
  11. ?static?void*?ThreadFunc(void?*?threadData);?//新線程的線程函數??
  12. ?static?int?MoveToIdle(pthread_t?tid);???//線程執行結束后,把自己放入到空閑線程中??
  13. ?static?int?MoveToBusy(pthread_t?tid);???//移入到忙碌線程中去??
  14. ?int?Create();??????????//創建所有的線程??
  15. public:??
  16. ?CThreadPool(int?threadNum);??
  17. ?int?AddTask(CTask?*task);??????//把任務添加到線程池中??
  18. ?int?StopAll();??
  19. };??

?

當線程池對象創建后,啟動一批線程,并把所有的線程放入空閑列表中,當有任務到達時,某一個線程取出任務并進行處理。

線程之間的同步用線程鎖和條件變量。

這個類的對外接口有兩個:

AddTask函數把任務添加到線程池的任務列表中,并通知線程進行處理。當任務到到時,把任務放入m_vecTaskList任務列表中,并用pthread_cond_signal喚醒一個線程進行處理。

StopAll函數停止所有的線程

?

Cpp代碼??收藏代碼
  1. ************************************************??
  2. ??
  3. 代碼:??
  4. ??
  5. ××××××××××××××××××××CThread.h??
  6. ??
  7. ???
  8. ??
  9. #ifndef?__CTHREAD??
  10. #define?__CTHREAD??
  11. #include?<vector>??
  12. #include?<string>??
  13. #include?<pthread.h>??
  14. ??
  15. using?namespace?std;??
  16. ??
  17. /**?
  18. 執行任務的類,設置任務數據并執行?
  19. **/??
  20. class?CTask??
  21. {??
  22. protected:??
  23. ?string?m_strTaskName;??//任務的名稱??
  24. ?void*?m_ptrData;???????//要執行的任務的具體數據??
  25. public:??
  26. ?CTask(){}??
  27. ?CTask(string?taskName)??
  28. ?{??
  29. ??this->m_strTaskName?=?taskName;??
  30. ??m_ptrData?=?NULL;??
  31. ?}??
  32. ?virtual?int?Run()=?0;??
  33. ?void?SetData(void*?data);????//設置任務數據??
  34. };??
  35. ??
  36. /**?
  37. 線程池?
  38. **/??
  39. class?CThreadPool??
  40. {??
  41. private:??
  42. ?vector<CTask*>?m_vecTaskList;?????????//任務列表??
  43. ?int?m_iThreadNum;????????????????????????????//線程池中啟動的線程數?????????????
  44. ?static?vector<pthread_t>?m_vecIdleThread;???//當前空閑的線程集合??
  45. ?static?vector<pthread_t>?m_vecBusyThread;???//當前正在執行的線程集合??
  46. ?static?pthread_mutex_t?m_pthreadMutex;????//線程同步鎖??
  47. ?static?pthread_cond_t?m_pthreadCond;????//線程同步的條件變量??
  48. protected:??
  49. ?static?void*?ThreadFunc(void?*?threadData);?//新線程的線程函數??
  50. ?static?int?MoveToIdle(pthread_t?tid);???//線程執行結束后,把自己放入到空閑線程中??
  51. ?static?int?MoveToBusy(pthread_t?tid);???//移入到忙碌線程中去??
  52. ?int?Create();??????????//創建所有的線程??
  53. public:??
  54. ?CThreadPool(int?threadNum);??
  55. ?int?AddTask(CTask?*task);??????//把任務添加到線程池中??
  56. ?int?StopAll();??
  57. };??
  58. ??
  59. #endif??
  60. ??
  61. ???
  62. ??
  63. ???
  64. ??
  65. ???
  66. ??
  67. 類的實現為:??
  68. ??
  69. ××××××××××××××××××××CThread.cpp??
  70. ??
  71. ???
  72. ??
  73. #include?"CThread.h"??
  74. #include?<string>??
  75. #include?<iostream>??
  76. ??
  77. using?namespace?std;??
  78. ??
  79. void?CTask::SetData(void?*?data)??
  80. {??
  81. ?m_ptrData?=?data;??
  82. }??
  83. ??
  84. vector<pthread_t>?CThreadPool::m_vecBusyThread;??
  85. vector<pthread_t>?CThreadPool::m_vecIdleThread;??
  86. pthread_mutex_t?CThreadPool::m_pthreadMutex?=?PTHREAD_MUTEX_INITIALIZER;??
  87. pthread_cond_t?CThreadPool::m_pthreadCond?=?PTHREAD_COND_INITIALIZER;??
  88. ??
  89. CThreadPool::CThreadPool(int?threadNum)??
  90. {??
  91. ?this->m_iThreadNum?=?threadNum;??
  92. ?Create();??
  93. }??
  94. int?CThreadPool::MoveToIdle(pthread_t?tid)??
  95. {??
  96. ?vector<pthread_t>::iterator?busyIter?=?m_vecBusyThread.begin();??
  97. ?while(busyIter?!=?m_vecBusyThread.end())??
  98. ?{??
  99. ??if(tid?==?*busyIter)??
  100. ??{??
  101. ???break;??
  102. ??}??
  103. ??busyIter++;??
  104. ?}??
  105. ?m_vecBusyThread.erase(busyIter);??
  106. ?m_vecIdleThread.push_back(tid);??
  107. ?return?0;??
  108. }??
  109. ??
  110. int?CThreadPool::MoveToBusy(pthread_t?tid)??
  111. {??
  112. ?vector<pthread_t>::iterator?idleIter?=?m_vecIdleThread.begin();??
  113. ?while(idleIter?!=?m_vecIdleThread.end())??
  114. ?{??
  115. ??if(tid?==?*idleIter)??
  116. ??{??
  117. ???break;??
  118. ??}??
  119. ??idleIter++;??
  120. ?}??
  121. ?m_vecIdleThread.erase(idleIter);??
  122. ?m_vecBusyThread.push_back(tid);??
  123. ?return?0;??
  124. }??
  125. void*?CThreadPool::ThreadFunc(void?*?threadData)??
  126. {??
  127. ?pthread_t?tid?=?pthread_self();??
  128. ?while(1)??
  129. ?{??
  130. ??pthread_mutex_lock(&m_pthreadMutex);??
  131. ??pthread_cond_wait(&m_pthreadCond,&m_pthreadMutex);??
  132. ??cout?<<?"tid:"?<<?tid?<<?"?run"?<<?endl;??
  133. ??//get?task??
  134. ??vector<CTask*>*?taskList?=?(vector<CTask*>*)threadData;??
  135. ??vector<CTask*>::iterator?iter?=?taskList->begin();??
  136. ??while(iter?!=?taskList->end())??
  137. ??{??
  138. ?????
  139. ???MoveToBusy(tid);??
  140. ???break;??
  141. ??}??
  142. ??CTask*?task?=?*iter;??
  143. ??taskList->erase(iter);??
  144. ??pthread_mutex_unlock(&m_pthreadMutex);??
  145. ??cout?<<?"idel?thread?number:"?<<?CThreadPool::m_vecIdleThread.size()?<<?endl;??
  146. ??cout?<<?"busy?thread?number:"?<<?CThreadPool::m_vecBusyThread.size()?<<?endl;??
  147. ??//cout?<<?"task?to?be?run:"?<<?taskList->size()?<<?endl;??
  148. ??task->Run();??
  149. ????
  150. ??//cout?<<?"CThread::thread?work"?<<?endl;??
  151. ??cout?<<?"tid:"?<<?tid?<<?"?idle"?<<?endl;??
  152. ????
  153. ?}??
  154. ?return?(void*)0;??
  155. }??
  156. ??
  157. int?CThreadPool::AddTask(CTask?*task)??
  158. {??
  159. ?this->m_vecTaskList.push_back(task);??
  160. ?pthread_cond_signal(&m_pthreadCond);??
  161. ?return?0;??
  162. }??
  163. int?CThreadPool::Create()??
  164. {??
  165. ?for(int?i?=?0;?i?<?m_iThreadNum;i++)??
  166. ?{??
  167. ??pthread_t?tid?=?0;??
  168. ??pthread_create(&tid,NULL,ThreadFunc,&m_vecTaskList);??
  169. ??m_vecIdleThread.push_back(tid);??
  170. ?}??
  171. ?return?0;??
  172. }??
  173. ??
  174. int?CThreadPool::StopAll()??
  175. {??
  176. ?vector<pthread_t>::iterator?iter?=?m_vecIdleThread.begin();??
  177. ?while(iter?!=?m_vecIdleThread.end())??
  178. ?{??
  179. ??pthread_cancel(*iter);??
  180. ??pthread_join(*iter,NULL);??
  181. ??iter++;??
  182. ?}??
  183. ??
  184. ?iter?=?m_vecBusyThread.begin();??
  185. ?while(iter?!=?m_vecBusyThread.end())??
  186. ?{??
  187. ??pthread_cancel(*iter);??
  188. ??pthread_join(*iter,NULL);??
  189. ??iter++;??
  190. ?}??
  191. ???
  192. ?return?0;??
  193. }??
  194. ??
  195. 簡單示例:??
  196. ??
  197. ××××××××test.cpp??
  198. ??
  199. #include?"CThread.h"??
  200. #include?<iostream>??
  201. ??
  202. using?namespace?std;??
  203. ??
  204. class?CWorkTask:?public?CTask??
  205. {??
  206. public:??
  207. ?CWorkTask()??
  208. ?{}??
  209. ?int?Run()??
  210. ?{??
  211. ??cout?<<?(char*)this->m_ptrData?<<?endl;??
  212. ??sleep(10);??
  213. ??return?0;??
  214. ?}??
  215. };??
  216. int?main()??
  217. {??
  218. ?CWorkTask?taskObj;??
  219. ?char?szTmp[]?=?"this?is?the?first?thread?running,haha?success";??
  220. ?taskObj.SetData((void*)szTmp);??
  221. ?CThreadPool?threadPool(10);??
  222. ?for(int?i?=?0;i?<?11;i++)??
  223. ?{??
  224. ??threadPool.AddTask(&taskObj);??
  225. ?}??
  226. ?while(1)??
  227. ?{??
  228. ??sleep(120);??
  229. ?}??
  230. ?return?0;??
  231. } ?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383823.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383823.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383823.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++學習筆記三】C++多態、抽象(接口)

當類之間存在多種層次結構&#xff0c;并且類之間通過繼承關聯時就會用到多態。 虛函數在子類中的覆蓋版本和該函數在基類中的原始版本必須有相同的函數簽名、函數名、形參名、常屬性。如果返回值為非類類型&#xff0c;則必須相同&#xff0c;如果是類類型A的指針或者引用&am…

C++重載和重寫的條件以及重寫后對基類函數的覆蓋

重載&#xff1a;同一個類中名字相同&#xff0c;參數列表不同的方法構成重載函數&#xff0c;和返回值沒有關系。這就意味著就算返回值不同&#xff0c;只要名字相同參數列表相同編譯器還是會報錯&#xff0c;覺得一函數被定義了兩次。 重寫&#xff1a;派生類中只要函數名字…

C++靜態成員和靜態方法

在類中&#xff0c;靜態成員可以實現多個對象之間共享數據&#xff0c;同時保證了安全性。靜態數據對該類的所有對象是公有的&#xff0c;存儲一處供所有對象使用。 注意&#xff1a; 靜態成員定義時需要在前面加上關鍵字static靜態成員必須初始化且必須在類外進行&#xff0…

基于epoll的簡單的http服務器

http://blog.csdn.net/fangjian1204/article/details/34415651 http服務器已經可以處理并發連接&#xff0c;支持多個客戶端并發訪問&#xff0c;每個連接可以持續讀寫數據&#xff0c;當然&#xff0c;這只是一個簡單的學習例子&#xff0c;還有很多bug&#xff0c;發表出來只…

C++單例模式簡單實現

有時候我們需要某個類只能被實例化一次&#xff0c;并且其他類都可以訪問到這個類&#xff0c;就需要這種設計模式。 例如我們想要做個資源管理器&#xff0c;顯然這個管理器只能有一個。 這種模式有很多實現方式&#xff0c;這里介紹最簡單的一種&#xff0c;想要了解更多可…

Linux C++ 實現線程池

http://blog.csdn.net/qq_25425023/article/details/53914609 線程池中的線程&#xff0c;在任務隊列為空的時候&#xff0c;等待任務的到來&#xff0c;任務隊列中有任務時&#xff0c;則依次獲取任務來執行&#xff0c;任務隊列需要同步。 Linux線程同步有多種方法&#xff…

C++制表符

制表符的轉義字符為\t&#xff0c;一般情況下長度為8個空格&#xff0c;這里的8個指的是從上一個字符串的開頭開始算&#xff0c;往后數8個&#xff0c;不夠的話就補空格。 如果前面的字符串的長度大于等于8個&#xff0c;例如前面字符串的長度為x,那么就會補(8-x%8)個空格 例…

C++派生類含有成員對象構造函數析構函數順序

參考博客&#xff1a;傳送門1 當類中含有對象成員時&#xff1a; 類的構造函數要包含對成員對象的初始化&#xff0c;如果構造函數的成員初始化列表沒有包含對成員對象的初始化&#xff0c;系統會自動調用成員對象的無參構造函數。順序上&#xff1a;先調用成員對象的構造函數…

c,c++中字符串處理函數strtok,strstr,strchr,strsub

http://blog.csdn.net/wangqing_12345/article/details/51760220 1&#xff0c;字符串切割函數 函數原型&#xff1a;char *strtok(char *s, char *delim); 函數功能&#xff1a;把字符串s按照字符串delim進行分割&#xff0c;然后返回分割的結果。 函數使用說&#xff1a; 1…

C++虛基類成員可見性

詳見《CPrimer》[第五版]719頁 如果繼承路徑上沒有和虛基類成員重名的成員&#xff0c;則不存在二義性&#xff0c;因為我們僅能訪問到虛基類成員。 當訪問僅有一條繼承路徑上含有和虛基類成員重名的成員&#xff0c;也不存在二義性。派生類的成員的優先級比基類的成員高&…

鏈表逆序的原理及實例

http://blog.csdn.net/wangqing_12345/article/details/51757294 尾插法建立鏈表&#xff0c;帶頭結點設鏈表節點為typedef struct node {int data;struct node *next;}node_t, *pnode_t;要求將一帶鏈表頭List head的單向鏈表逆序。 分析&#xff1a; 1). 若鏈表為空或只有一個…

C++關于虛基類、構造函數、析構函數、成員對象的兩個程序淺析

預備博客&#xff1a; C虛繼承中構造函數和析構函數順序問題以及原理 C派生類含有成員對象構造函數析構函數順序 C虛基類成員可見性 程序一如下&#xff1a; #include<iostream> using namespace std; class A { public:A(int a) :x(a) { cout << "A const…

strtok函數及其實現

頭文件&#xff1a;#include <string.h> 定義函數&#xff1a;char * strtok(char *s, const char *delim); 函數說明&#xff1a;strtok()用來將字符串分割成一個個片段。參數s 指向欲分割的字符串&#xff0c;參數delim 則為分割字符串&#xff0c;當 strtok()在參數s …

C++小型公司管理系統

項目要求&#xff1a; 編寫一個程序實現小型公司的人員信息管理系統。該公司雇員&#xff08;employee&#xff09;包括經理&#xff08;manager&#xff09;&#xff0c;技術人員&#xff08;technician&#xff09;、銷售員&#xff08;salesman&#xff09;和銷售部經理&…

Linux網絡編程“驚群”問題總結

http://www.cnblogs.com/Anker/p/7071849.html 1、前言 我從事Linux系統下網絡開發將近4年了&#xff0c;經常還是遇到一些問題&#xff0c;只是知其然而不知其所以然&#xff0c;有時候和其他人交流&#xff0c;搞得非常尷尬。如今計算機都是多核了&#xff0c;網絡編程框架也…

【Java學習筆記六】常用數據對象之String

字符串 在Java中系統定義了兩種類型的字符串類&#xff1a;String和StringBuffer String類對象的值和長度都不能改變&#xff0c;稱為常量字符串類&#xff0c;其中每個值稱為常量字符串。 StringBuffer類對象的值和長度都可以改變&#xff0c;稱為變量字符串類&#xff0c;其…

【Java學習筆記七】常用數據對象之數組

同一般的對象創建和定義一樣&#xff0c;數組的定義和創建可以分開進行也可以合并一起進行。 一維數組定義格式&#xff1a; <元素類型>[] <數組名>;//[]也可以放在數組名的后面一維數組創建格式&#xff1a; new <元素類型>[<元素個數>];執行new運…

yfan.qiu linux硬鏈接與軟鏈接

http://www.cnblogs.com/yfanqiu/archive/2012/06/11/2545556.html Linux 系統中有軟鏈接和硬鏈接兩種特殊的“文件”。 軟鏈接可以看作是Windows中的快捷方式&#xff0c;可以讓你快速鏈接到目標檔案或目錄。 硬鏈接則透過文件系統的inode來產生新檔名&#xff0c;而不是產生…

【Java學習筆記八】包裝類和vector

包裝類 在Java語言中&#xff0c;每一種基本的數據類型都有相應的對象類型&#xff0c;稱為他們基本類型的包裝類&#xff08;包裹類&#xff09;。 字節byte&#xff1a;Byte、短整數型short&#xff1a;Short 標準整數型int&#xff1a;Integer、長整數型long&#xff1a;Lo…

Linux C++線程池實例

http://www.cnblogs.com/danxi/p/6636095.html 想做一個多線程服務器測試程序&#xff0c;因此參考了github的一些實例&#xff0c;然后自己動手寫了類似的代碼來加深理解。 目前了解的線程池實現有2種思路&#xff1a; 第一種&#xff1a; 主進程創建一定數量的線程&#xff0…