国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

利用C++語言設計可擴展線程池

2019-11-17 05:23:34
字體:
來源:轉載
供稿:網友
摘要:在各種業務解決方案的設計中,服務器處理任務的效率是衡量方案優劣的一個重要標準。使用多線程技術并發處理任務是提高服務器效率的一個主要手段。但是頻繁的線程創建、銷毀和任務的分配也會降低系統效率。本文設計了一個通用的線程池,根據不同服務器所處理的任務的特點,可以設置對應的線程池參數,最大幅度的提高系統性能。

  要害字:線程池多線程任務虛函數異常

  概述

  在各種業務解決方案的設計過程中,服務器處理任務的效率往往決定了方案的成敗。多線程處理任務是提高服務器效率的主要手段,它提高了對服務器資源的利用,使得任務可以并發處理。但假如服務器處理的任務的特點是輕量級、頻率高,那么線程的創建與銷毀會非常頻繁,而系統用于處理線程的創建與銷毀的開銷會占相當大的比重,反而降低了系統的效率。通過線程池技術,可以減少頻繁的線程的創建與銷毀對系統性能的影響。

  線程池是預先創建線程的一種技術。線程池在還沒有任務到來之前,創建一定數量(N1)的線程,放入空閑隊列中。這些線程都是處于阻塞(Suspended)狀態,不消耗CPU,但占用較小的內存空間。當任務到來后,緩沖池選擇一個空閑線程,把任務傳入此線程中運行。當N1個線程都在處理任務后,緩沖池自動創建一定數量的新線程,用于處理更多的任務。當系統比較空閑時,大部分線程都一直處于暫停狀態,線程池自動銷毀一部分線程,回收系統資源。

  通用線程緩沖池的設計,不僅要實現上述功能,還要考慮此設計的可移植性,減少重復開發。設計中需要考慮的重點是:
  • 任務對象的通用性;
  • 線程創建和銷毀策略;
  • 任務的分配策略。
  分析與設計

  1、任務對象的通用性

  不同的業務解決方案有各自獨特的任務處理方法,任務的劃分上也就千差萬別。為了使得在處理任務對象的時候達到一定程度的通用性,任務對象的設計上必須與實際任務的處理邏輯完全無關。從任務執行的角度看,任務不過是處理流程的一次或者多次執行的過程,可以這樣來定義任務接口:

class Task

{

public:

Task();

virtual ~Task();

virtual bool run() = 0;

};
  Task類是所有任務類的基類,其中的純虛函數run()是任務流程的入口,工作線程在處理任務的時候就從此處開始執行任務的處理流程。設計一個新的任務時,只需要繼續Task接口,新的任務就可以放入線程池中執行。

  任務的創建、執行和銷毀這樣來設計:

  (1)任務在其需要的時候才創建。任務的創建通過new操作,動態創建具體的任務對象,然后傳入線程池,由線程池自動分配線程來執行此任務。

  (2)任務是否執行完畢由其自身來決定。一個未知任務什么時候執行完畢是不可能猜測的,必須任務本身來決定。這個策略通過,Task::run()的返回值來實現。當工作線程執行一次任務時,假如返回值為true,表示任務執行完畢,就用delete操作銷毀此任務;假如返回值為false,表示任務需要執行的工作并未完成,繼續執行此任務。

  這樣的策略,使得在設計新的任務處理流程的時候,不需要過多的關心任務的接口規范,只需要在新任務類的構造函數中初始化各種資源,在新任務類的析構函數中回收資源,在run()方法中實現主要的處理邏輯,那么新的任務類即可在線程池中執行。

  2、線程的創建與銷毀

  線程緩沖池中的維持的線程數量應該按照任務處理的需求來定。

  在緩沖池剛剛建立時,線程池中有一定數量(N1)的已創建好的線程,這樣可以使得新任務可以及時的得到執行。比如,某客戶端在向服務器發送登陸請求的時候,這樣一個請求使得服務器通常需要創建好幾個相互有關聯的任務。也就是說,客戶端與服務器端的一次交互,通常會產生一定數量的任務。根據一個服務器所處理的業務,估計出平均情況下,一次業務產生的任務數量N2。那么N1應該是N2的整數倍,N1=N2×n1,減少由于線程不夠而再創建線程的概率,才能使得服務器在業務處理初期最為高效。

  在線程緩沖池中的所有線程都處于繁忙狀態的時候,線程池就會創建新的線程,設創建N3個。由以上分析,為了減少由于線程不夠而再創建線程的概率,N3也應該是N2的整數倍,N3=N2×n2。

  當服務器業務減少,出現大量線程閑置的情況,就應該銷毀一部分線程。很顯然,這里應該使用超時策略,當某些線程在超過時間T仍然處于閑置狀態,就銷毀一部分空閑線程。設銷毀N4個空閑線程,為了減少由于線程不夠而再創建線程的概率,N4也應該是N2的整數倍,N4=N2×n3。當然,為了使得新任務及時得到處理,即使服務器一直處于空閑,也應該保留N1個線程。   3、任務分配策略

  在業務處理中,會有各種各樣的任務對象,這些業務對象對系統資源的使用也不同。這些任務,無論其空間復雜度如何,從線程執行任務這一角度來看,應該關心的主要是時間復雜度。

  線程緩沖池在接收到新任務的時候,首先要尋找空閑線程,傳入新任務,然后執行任務,最后還要刪除任務,置空閑線程的標志。尋找空閑線程、傳入任務、最后的清理工作,這些都是為了執行任務而產生的額外開銷,假如所執行的任務大多數都是輕量級任務,那么額外開銷帶來的資源浪費就顯得很突出了。為了解決這個問題,可以給一個線程傳入N5個輕量級任務,這一個線程依次執行N5個輕量級任務,由于都是在很短時間內完成,并不影響任務響應的及時性。顯然,N5≥1。

  實現

  由于源代碼的篇幅關系,并不能把所有代碼一一列舉,這里以偽代碼的形式給出線程緩沖池在線程的創建、銷毀、任務分配以及任務執行方面的流程。

  (1) 線程池任務分配主循環(也是一個線程)

  這里除了任務分配算法外也包括了部分線程的創建與銷毀的算法。


for(;;) {

pThread = GetIdleThread();// 檢查空閑線程隊列

if( pThread != NULL ) {

if( CheckNewTask() ) {// 有新任務

TaskList tl;

GetTask( tl ); // 取得一定數量的任務

AddTaskToThread( pTask, tl );// 把任務傳入線程

continue; // 繼續循環

}

}

if( pThread == NULL && nThread < THREAD_MAX )// 沒有空閑線程了

CreateNewThread();// 創建新線程

continue;// 繼續循環

}

// 沒有要處理的任務或者已經到達線程數的上限,進入超時等待

if( WaitForTaskOrThreadTimeout() ) {

if( IncrIdleTime() > IDLE_MAX ) { // 系統空閑,計時

// 系統長時間處于空閑,銷毀一定數量的空閑線程

DecrIdleThread();

}

}

else

return 0;// 線程終止

}
    (2) 工作線程的任務執行流程

for(;;) {

// 檢查任務隊列是否有任務要運行

if( !CheckTaskQueue() ) { // 隊列中沒有任務

pPool->OnTaskIdle( this ); // 通知線程池,此線程已經空閑

if( WaitForTask() )

continue;// 繼續循環

else

return 0;// 終止線程

} else { // 有任務需要運行

pTask = GetTask(); // 取得新任務

try {

while( !pTask->Run() ) {

// 此處循環體為空,不斷運行直到任務執行完畢

}

}

catch( … ) {

WriteLog( … ); // 執行任務時產生異常,記錄入日志

}

delete pTask; // 任務執行完畢,刪除此任務

}

}
  在任務執行的核心部分,使用了try-catch控制塊進行異常捕捉。雖然異常會對程序速度有很略微的影響,但是因為要執行的任務是未知的,不能保證任務可以正常執行。因為一個任務的異常而導致服務器的服務程序崩潰,這是絕對不答應的。使用異常捕捉不僅可以保證服務器流程的順利執行,而且把異常信息存入日志文件,還可以跟蹤錯誤。

  性能測試

  為了檢驗此線程池的性能是否和預期相同,并且分析出線程池的不同參數配置對系統性能的影響,特編寫了測試程序對三組參數進行了測試,測試結果如圖1所示:

利用C++語言設計可擴展線程池(圖一)
利用C++語言設計可擴展線程池(圖二)

  橫坐標是任務數量;縱坐標是消耗時間,以(s)為單位。

  參數1:N2 = 1, N5 = 1; 參數2:N2 = 5, N5 = 1; 參數3:N2 = 5, N5 = 5

  測試中,系統的總的線程數限制為500,任務都是5ms。這里只針對N2和N5進行測試,N2是平均情況下系統每次向線程池中增加的任務數量,N5是每個線程一次執行任務數量。

  在任務量比較小的情況下,三者的對系統性能的占用基本上相等。但是當任務量很巨大的時候,參數1比參數2效率要稍微高出一些,而參數3的執行效率幾乎是前兩者的一倍。

  因為都是輕量級任務,所以N2的變化對系統效率的影響并不大,而N5的影響就很顯著。

  結束語

  通過測試可以看出,在服務器中使用線程池后,并不意味著系統性能就一定可以提升。不同系統的任務有著各自不同的特點,這就需要根據服務器任務的特點進一步調整緩沖池的一些要害參數,才能最大程度的提高系統效率。這些參數就是上面分析過程中的N1、N2、N3、N4、N5、n1、n2、n3。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 虎林市| 云阳县| 盐源县| 昆山市| 中山市| 镶黄旗| 大田县| 阜南县| 澳门| 迁西县| 仁布县| 榆树市| 东乡县| 沁阳市| 遂溪县| 中宁县| 宜昌市| 云梦县| 承德市| 青川县| 博罗县| 霍邱县| 辉县市| 富蕴县| 方城县| 西和县| 同德县| 博野县| 徐水县| 阳城县| 大石桥市| 理塘县| 汤阴县| 二连浩特市| 五原县| 方正县| 广平县| 荣成市| 揭西县| 巢湖市| 涿州市|