日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

利用C++语言设计可扩展线程池

發(fā)布時間:2025/3/15 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用C++语言设计可扩展线程池 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

  摘要:在各種業(yè)務(wù)解決方案的設(shè)計中,服務(wù)器處理任務(wù)的效率是衡量方案優(yōu)劣的一個重要標(biāo)準(zhǔn)。使用多線程技術(shù)并發(fā)處理任務(wù)是提高服務(wù)器效率的一個主要手段。但是頻繁的線程創(chuàng)建、銷毀和任務(wù)的分配也會降低系統(tǒng)效率。本文設(shè)計了一個通用的線程池,根據(jù)不同服務(wù)器所處理的任務(wù)的特點(diǎn),可以設(shè)置對應(yīng)的線程池參數(shù),最大幅度的提高系統(tǒng)性能。

  關(guān)鍵字:線程池多線程任務(wù)虛函數(shù)異常

  概述

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

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

  通用線程緩沖池的設(shè)計,不僅要實(shí)現(xiàn)上述功能,還要考慮此設(shè)計的可移植性,減少重復(fù)開發(fā)。設(shè)計中需要考慮的重點(diǎn)是:

任務(wù)對象的通用性;
線程創(chuàng)建和銷毀策略;
任務(wù)的分配策略。
  分析與設(shè)計

  1、任務(wù)對象的通用性

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

class Task

{

public:

Task();

virtual ~Task();

virtual bool run() = 0;

};

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

  任務(wù)的創(chuàng)建、執(zhí)行和銷毀這樣來設(shè)計:

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

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

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

  2、線程的創(chuàng)建與銷毀

  線程緩沖池中的維持的線程數(shù)量應(yīng)該按照任務(wù)處理的需求來定。

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

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

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

  在業(yè)務(wù)處理中,會有各種各樣的任務(wù)對象,這些業(yè)務(wù)對象對系統(tǒng)資源的使用也不同。這些任務(wù),無論其空間復(fù)雜度如何,從線程執(zhí)行任務(wù)這一角度來看,應(yīng)該關(guān)心的主要是時間復(fù)雜度。

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

  實(shí)現(xiàn)

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

  (1) 線程池任務(wù)分配主循環(huán)(也是一個線程)

  這里除了任務(wù)分配算法外也包括了部分線程的創(chuàng)建與銷毀的算法。

for(;;) {

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

if( pThread != NULL ) {

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

TaskList tl;

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

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

continue; // 繼續(xù)循環(huán)

}

}

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

CreateNewThread();// 創(chuàng)建新線程

continue;// 繼續(xù)循環(huán)

}

// 沒有要處理的任務(wù)或者已經(jīng)到達(dá)線程數(shù)的上限,進(jìn)入超時等待

if( WaitForTaskOrThreadTimeout() ) {

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

// 系統(tǒng)長時間處于空閑,銷毀一定數(shù)量的空閑線程

DecrIdleThread();

}

}

else

return 0;// 線程終止

}

  (2) 工作線程的任務(wù)執(zhí)行流程

for(;;) {

// 檢查任務(wù)隊(duì)列是否有任務(wù)要運(yùn)行

if( !CheckTaskQueue() ) { // 隊(duì)列中沒有任務(wù)

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

if( WaitForTask() )

continue;// 繼續(xù)循環(huán)

else

return 0;// 終止線程

} else { // 有任務(wù)需要運(yùn)行

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

try {

while( !pTask->Run() ) {

// 此處循環(huán)體為空,不斷運(yùn)行直到任務(wù)執(zhí)行完畢

}

}

catch( … ) {

WriteLog( … ); // 執(zhí)行任務(wù)時產(chǎn)生異常,記錄入日志

}

delete pTask; // 任務(wù)執(zhí)行完畢,刪除此任務(wù)

}

}

  在任務(wù)執(zhí)行的核心部分,使用了try-catch控制塊進(jìn)行異常捕獲。雖然異常會對程序速度有很略微的影響,但是因?yàn)橐獔?zhí)行的任務(wù)是未知的,不能保證任務(wù)可以正常執(zhí)行。因?yàn)橐粋€任務(wù)的異常而導(dǎo)致服務(wù)器的服務(wù)程序崩潰,這是絕對不允許的。使用異常捕獲不僅可以保證服務(wù)器流程的順利執(zhí)行,而且把異常信息存入日志文件,還可以跟蹤錯誤。

  性能測試

  為了檢驗(yàn)此線程池的性能是否和預(yù)期相同,并且分析出線程池的不同參數(shù)配置對系統(tǒng)性能的影響,特編寫了測試程序?qū)θM參數(shù)進(jìn)行了測試,測試結(jié)果如圖1所示:




  橫坐標(biāo)是任務(wù)數(shù)量;縱坐標(biāo)是消耗時間,以 秒(s)為單位。

  參數(shù)1:N2 = 1, N 5 = 1; 參數(shù)2:N2 = 5, N5 = 1; 參數(shù)3:N2 = 5, N5 = 5

  測試中,系統(tǒng)的總的線程數(shù)限制為500,任務(wù)都是5ms。這里只針對N2和N5進(jìn)行測試,N2是平均情況下系統(tǒng)每次向線程池中增加的任務(wù)數(shù)量,N5是每個線程一次執(zhí)行任務(wù)數(shù)量。

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

  因?yàn)槎际禽p量級任務(wù),所以N2的變化對系統(tǒng)效率的影響并不大,而N5的影響就很顯著。

   結(jié)束語

  通過測試可以看出,在服務(wù)器中使用線程池后,并不意味著系統(tǒng)性能就一定可以提升。不同系統(tǒng)的任務(wù)有著各自不同的特點(diǎn),這就需要根據(jù)服務(wù)器任務(wù)的特點(diǎn)進(jìn)一步調(diào)整緩沖池的一些關(guān)鍵參數(shù),才能最大程度的提高系統(tǒng)效率。這些參數(shù)就是上面分析過程中的N1、N2、N3、N4、N5、n1、n2、n3。

總結(jié)

以上是生活随笔為你收集整理的利用C++语言设计可扩展线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。