日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

Windows下一个比较完美的线程池实现

發(fā)布時(shí)間:2025/3/21 windows 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Windows下一个比较完美的线程池实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1.??前言

線程池不是一個(gè)新鮮的東西,網(wǎng)上能找到很多原理、實(shí)現(xiàn),甚至很多庫(kù)都提供了實(shí)現(xiàn),比如微軟的 ATL::CThreadPool, Vista后提供的CreateThreadpoolWork, boost 中提供的 thread_pool, CSDN、CodeProject 等網(wǎng)站上很多人已經(jīng)實(shí)現(xiàn)的類。但這些庫(kù)往往只支持啟動(dòng)任務(wù),而不能很好地停止任務(wù)(相信很多人都會(huì)和我一樣有這個(gè)需求),于是我在FTL中寫了一個(gè)個(gè)人認(rèn)為還比較完美的線程池。

2.??功能

本線程池提供了如下功能:

1.?????? 能根據(jù)任務(wù)個(gè)數(shù)和當(dāng)前線程的多少在最小/最大線程個(gè)數(shù)之間自動(dòng)調(diào)整(Vista后的系統(tǒng)有 SetThreadpoolThreadMaximum 等函數(shù)有類似功能);

2.??????能方便的對(duì)任一任務(wù)進(jìn)行取消操作,無(wú)論該任務(wù)是等待運(yùn)行狀態(tài)還是正在運(yùn)行狀態(tài)都支持(相比較而言,WaitForThreadpoolWorkCallbacks 函數(shù)只能取消尚未運(yùn)行的任務(wù));

3.??????能對(duì)整個(gè)線程池進(jìn)行安全的暫停、繼續(xù)、停止處理

4.??????支持回調(diào)方式的反饋通知

5.??????使用模版方式實(shí)現(xiàn),能方便的進(jìn)行參數(shù)傳遞

6.??????在加入任務(wù)時(shí)可以設(shè)置優(yōu)先級(jí)(目前尚不支持動(dòng)態(tài)調(diào)整)

7.??????使用的是微軟的基本API,能支持WinXP、Vista、Win7等各種操作系統(tǒng)(CreateThreadpoolWork 等只能在Vista后才能使用)

3.??UML圖示和簡(jiǎn)單說(shuō)明

其UML圖比較簡(jiǎn)單,主要的只有三個(gè)類:

CFThreadPool – 線程池的管理類,負(fù)責(zé)整個(gè)線程池的管理工作,直接使用即可。

CFJobBase – Job的基類,如果想實(shí)現(xiàn)自己的Job,必須從這個(gè)類繼承,并實(shí)現(xiàn)其中的Run/ OnCancelJob 等函數(shù)。

IFThreadPoolCallBack– 可選的回調(diào)實(shí)現(xiàn),可以通知調(diào)用段 Job 的啟動(dòng)、停止、取消、進(jìn)度通知、錯(cuò)誤等各種狀態(tài)的改變。

4.??實(shí)現(xiàn)說(shuō)明

以下部分簡(jiǎn)單介紹了一些比較重要的代碼實(shí)現(xiàn),具體請(qǐng)參見(jiàn)示例代碼和其中的注釋部分。

4.1.?????Job容器

本線程池類中有兩種Job的容器,分別是等待運(yùn)行的Jobs和當(dāng)前正在運(yùn)行的Jobs。因?yàn)橛胁煌男枨?#xff0c;其定義分別如下(兩種容器類型的選擇,其理由已經(jīng)寫得比較詳細(xì),大家自行分析即可)

???? //! 保存等待Job的信息,由于有優(yōu)先級(jí)的問(wèn)題,而且從最前面開(kāi)始取任務(wù),因此保存成set

//! 保證優(yōu)先級(jí)高、JobIndex小(同優(yōu)先級(jí)時(shí)FIFO) 的Job在最前面

???? typedeftypenameUnreferenceLess<CFJobBase<T>* >JobBaseUnreferenceLess;

???? typedefstd::set<CFJobBase<T>*,JobBaseUnreferenceLess > WaitingJobContainer;

???? WaitingJobContainer????????m_WaitingJobs;????//!等待運(yùn)行的Job

?

???? //! 保存運(yùn)行Job的信息,由于會(huì)頻繁加入、刪除,且需要按照J(rèn)obIndex查找刪除,因此保存成map

???? typedefstd::map<LONG,CFJobBase<T>* >???DoingJobContainer;

???? DoingJobContainer????? m_DoingJobs;? //! 正在運(yùn)行的Job

?

4.2.?????Job優(yōu)先級(jí)

代碼中通過(guò)operator < 方法比較CFJobBase<T>::m_nJobPriority和 JobIndex,在SubmitJob時(shí)保證其在 set 中的順序來(lái)保證 優(yōu)先級(jí)高的Job先執(zhí)行,相同優(yōu)先級(jí)的Job采用FIFO方式。

4.3.?????Job對(duì)暫停、停止的支持

為了支持暫停、停止,Job的子類必須在工作循環(huán)中調(diào)用父類提供 GetJobWaitType方法,并判斷其返回值。如果返回值為ftwtStop 表示用戶請(qǐng)求了停止,需要進(jìn)行必要的清除工作。GetJobWaitType的實(shí)現(xiàn)請(qǐng)參見(jiàn)代碼(本質(zhì)是等待m_hEventJobStop, m_pThreadPool->m_hEventStop, m_pThreadPool->m_hEventContinue這三個(gè)手動(dòng)重置事件之一)

4.4.?????線程池對(duì)Job的控制

線程池中主要有以下的一些函數(shù),因?yàn)橐饬x根據(jù)名字很容易猜出,就不再詳細(xì)介紹,詳見(jiàn)示例。

Start(LONGnMinNumThreads, LONG nMaxNumThreads);

StopAndWait(DWORDdwTimeOut = FTL_MAX_THREAD_DEADLINE_CHECK);

ClearUndoWork();

SubmitJob(CFJobBase<T>*pJob, LONG* pOutJobIndex); //加入Job,會(huì)返回Job在Pool中的唯一索引,可以通過(guò)CancelJob 取消。

Pause/Resume/Stop// 對(duì)整個(gè)線程池請(qǐng)求暫停、繼續(xù)、停止的操作。注意:需要Job子類的配合才能達(dá)成目標(biāo)。

4.5.?????資源的處理

CFJobBase子類需要 Initialize、Run、Finalize、OnCancelJob 這幾個(gè)虛函數(shù)。

當(dāng)Job運(yùn)行的時(shí)候,其邏輯為 if(Initialize){ Run -> Finalize; },需要在 Finalize 中釋放資源;

當(dāng)Job沒(méi)有運(yùn)行的時(shí)候就被取消或Pool停止,則會(huì)調(diào)用 OnCancelJob,需要在其中釋放資源。

5.??示例程序

編寫了簡(jiǎn)單的MFC示例程序,其界面如圖所示:

因?yàn)閁I不是重點(diǎn),而且本人也比較懶,所以沒(méi)有弄很好的UI出來(lái),所有的運(yùn)行信息請(qǐng)參見(jiàn)VisualStudio中的“輸出”窗口。

Start 按鈕啟動(dòng)線程池,示例中設(shè)置的最小、最大線程個(gè)數(shù)是 2-4(即會(huì)根據(jù)加入的Job自動(dòng)在 2-4 個(gè)線程之間自動(dòng)調(diào)整)。

?????? 三個(gè)AddJob按鈕分別是增加 高、普通、低優(yōu)先級(jí)的Job,加入后可以在日志中查看其運(yùn)行的順序。

?????? 兩個(gè)CancelJob按鈕分別是從前面、后面的JobIndex取消Job(實(shí)際上支持任和有效的JobIndex)。

??????

6.??特別說(shuō)明

6.1.?????IFThreadPoolCallBack 回調(diào)的同步

Pool 調(diào)用 IFThreadPoolCallBack 接口的各個(gè)方法時(shí),為了性能上的考慮,沒(méi)有加鎖進(jìn)行同步。使用時(shí)如果有需要,最好自行同步。

6.2.?????單任務(wù)的暫停、繼續(xù) VS Pool的暫停、繼續(xù)

在開(kāi)發(fā)過(guò)程中,考慮過(guò)是提供單任務(wù)的暫停、繼續(xù) 還是 整個(gè)Pool 的暫停、繼續(xù),考慮到目前的需求,暫時(shí)只支持整個(gè)Pool的暫停,免得過(guò)分復(fù)雜,如有需要,大家可以自行參考CancelJob實(shí)現(xiàn)。

6.3.?????可能存在的Bug和解決方法

在開(kāi)發(fā)的過(guò)程中,對(duì)各個(gè)部分都進(jìn)行了詳細(xì)的分析、考慮和測(cè)試,應(yīng)該沒(méi)有較大的Bug。目前只想到一種在極端情況下,可能會(huì)造成的Bug,特提出以免各位踩雷。

描述:因?yàn)槭嵌嗑€程的代碼,所以在極端情況下,可能出現(xiàn)SubmitJob函數(shù)尚未返回,對(duì)應(yīng)的Job就執(zhí)行完畢(或 Initialize失敗直接返回)的情況。此時(shí)如果調(diào)用端采用了將 *pOutJobIndex保存起來(lái),在 OnJobEnd 中清除的邏輯,可能會(huì)因?yàn)?OnJobEnd 找不到對(duì)應(yīng)的JobIndex 而出現(xiàn)邏輯錯(cuò)誤。

解決方法:在調(diào)用 SubmitJob 的代碼和OnJobEnd 的回調(diào)代碼中,使用相同的鎖機(jī)制保證即可(這個(gè)也應(yīng)該由調(diào)用者來(lái)保證)。

源碼和示例程序的下載地址請(qǐng)參見(jiàn)本人的資源列表(可能需要等一段CSDN刷新的時(shí)間)。

http://download.csdn.net/detail/fishjam/5106672

總結(jié)

以上是生活随笔為你收集整理的Windows下一个比较完美的线程池实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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