C# ThreadPool

在多線程的程序中,經(jīng)常會(huì)出現(xiàn)兩種情況:?

? ? ? 1. 應(yīng)用程序中線程把大部分的時(shí)間花費(fèi)在等待狀態(tài),等待某個(gè)事件發(fā)生,然后給予響應(yīng)拆宛。這一般使用ThreadPool(線程池)來解決嗓奢。

? ? ? 2. 線程平時(shí)都處于休眠狀態(tài)讼撒,只是周期性地被喚醒。這一般使用Timer(定時(shí)器)來解決股耽。

線程 Thread 有兩種:【前臺(tái)線程】和【后臺(tái)線程】根盒,我們可以通過線程屬性IsBackground?來指定線程的前后臺(tái)屬性(默認(rèn)是前臺(tái)線程);

兩者的主要區(qū)別是:進(jìn)程會(huì)等待所有的前臺(tái)線程完成后再結(jié)束工作物蝙,但是如果只剩下后臺(tái)線程炎滞,則會(huì)直接結(jié)束工作。

(一個(gè)重要注意事項(xiàng)是如果程序定義了一個(gè)不會(huì)完成的前臺(tái)線程诬乞,主程序并不會(huì)正常結(jié)束)

.Net環(huán)境使用 Thread 建立的線程默認(rèn)情況下為前臺(tái)線程册赛,即線程屬性 IsBackground = false;在進(jìn)程中震嫉,只要有一個(gè)前臺(tái)線程未退出森瘪,進(jìn)程就不會(huì)終止。主線程就是一個(gè)前臺(tái)線程票堵。后臺(tái)線程不管線程是否結(jié)束扼睬,只要所有前臺(tái)線程都退出(包括正常退出和異常退出)后,進(jìn)程就會(huì)自動(dòng)終止悴势。一般后臺(tái)線程用于處理時(shí)間較短的任務(wù)窗宇,如一個(gè)Web服務(wù)器中可以利用后臺(tái)線程來處理客戶端發(fā)過來的請(qǐng)求信息。而前臺(tái)線程用來處理需要長(zhǎng)時(shí)間等待的任務(wù)特纤,如在Web服務(wù)器中的監(jiān)聽客戶端請(qǐng)求的程序军俊,或是定時(shí)對(duì)某些系統(tǒng)資源進(jìn)行掃描的程序。

在什么情況下使用線程池捧存??

? ? ? 1.單個(gè)任務(wù)處理的時(shí)間比較短

? ? ? 2.將需處理的任務(wù)的數(shù)量大?

? ? ? 3.多線程的環(huán)境中粪躬,盡量采用線程池

線程池的大小

不管什么池官硝,總有尺寸,ThreadPool也不例外短蜕。ThreadPool提供了4個(gè)方法來調(diào)整線程池的大星饧堋:

SetMaxThreads

GetMaxThreads

SetMinThreads

GetMinThreads

SetMaxThreads指定線程池最多可以有多少個(gè)線程,而GetMaxThreads自然就是獲取這個(gè)值朋魔。SetMinThreads指定線程池中最少存活的線程的數(shù)量岖研,而GetMinThreads就是獲取這個(gè)值。

為何要設(shè)置一個(gè)最大數(shù)量和有一個(gè)最小數(shù)量呢警检?原來線程池的大小取決于若干因素孙援,如虛擬地址空間的大小等。比如你的計(jì)算機(jī)是4G內(nèi)存扇雕,而一個(gè)線程的初始堆棧大小為1M拓售,那么你最多能創(chuàng)建4G/1M的線程(忽略操作系統(tǒng)本身以及其他進(jìn)程內(nèi)存分配);正因?yàn)榫€程有內(nèi)存開銷镶奉,所以如果線程池的線程過多而又沒有被完全使用础淤,那么這就是對(duì)內(nèi)存的一種浪費(fèi),所以限制線程池的最大數(shù)是很make sense的哨苛。

那么最小數(shù)又是為啥鸽凶?線程池就是線程的對(duì)象池,對(duì)象池的最大的用處是重用對(duì)象建峭。為啥要重用線程玻侥,因?yàn)榫€程的創(chuàng)建與銷毀都要占用大量的CPU時(shí)間。所以在高并發(fā)狀態(tài)下亿蒸,線程池由于無需創(chuàng)建銷毀線程節(jié)約了大量時(shí)間凑兰,提高了系統(tǒng)的響應(yīng)能力和吞吐量。最小數(shù)可以讓你調(diào)整最小的存活線程數(shù)量來應(yīng)對(duì)不同的高并發(fā)場(chǎng)景边锁。

使用線程池的好處姑食?

在多線程編程時(shí),如果創(chuàng)建了過多的線程將會(huì)增加操作系統(tǒng)資源的占用砚蓬,并且還要處理資源要求和潛在的占用沖突矢门,并且使用了多線程之后將使代碼的執(zhí)行流程和資源競(jìng)爭(zhēng)情況變得復(fù)雜,稍不留心就會(huì)產(chǎn)生Bug灰蛙。在使用多線程編程時(shí)對(duì)需要同步的資源訪問尤其需要注意祟剔,如系統(tǒng)資源(系統(tǒng)端口等)、共享資源(文件摩梧、窗口句柄等)物延、屬于單個(gè)應(yīng)用程序的資源(如全局、靜態(tài)和實(shí)例字段或?qū)傩裕?/p>

針對(duì)上面的情況仅父,我們可以使用線程池來解決上面的大部分問題叛薯,跟使用單個(gè)線程相比浑吟,使用線程池有如下優(yōu)點(diǎn):

1、縮短應(yīng)用程序的響應(yīng)時(shí)間耗溜。因?yàn)樵诰€程池中有的線程處于等待分配任務(wù)狀態(tài)(只要沒有超過線程池的最大上限)组力,無需創(chuàng)建線程。

2抖拴、不必管理和維護(hù)生存周期短暫的線程燎字,不用在創(chuàng)建時(shí)為其分配資源,在其執(zhí)行完任務(wù)之后釋放資源阿宅。

3候衍、線程池會(huì)根據(jù)當(dāng)前系統(tǒng)特點(diǎn)對(duì)池內(nèi)的線程進(jìn)行優(yōu)化處理。

4洒放、減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開銷蛉鹿,如不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量線程而導(dǎo)致消耗完系統(tǒng)內(nèi)存以及”過度切換”往湿。


總之使用線程池的作用就是減少創(chuàng)建和銷毀線程的系統(tǒng)開銷妖异。在.NET中有一個(gè)線程的類ThreadPool,它提供了線程池的管理煌茴。

ThreadPool 類是一個(gè)靜態(tài)類随闺,你不能也不必要生成它的對(duì)象。而且一旦使用該方法在線程池中添加了一個(gè)項(xiàng)目蔓腐,那么該項(xiàng)目將是無法取消的。這里你無需自己建立線程龄句,只需把你要做的工作寫成函數(shù)回论,然后作為參數(shù)傳遞給ThreadPool.QueueUserWorkItem()方法就行了,傳遞的方法就是依靠 WaitCallback 代理對(duì)象分歇,而線程的建立傀蓉、管理、運(yùn)行等工作都是由系統(tǒng)自動(dòng)完成的职抡,你無須考慮那些復(fù)雜的細(xì)節(jié)問題葬燎。

ThreadPool是一個(gè)靜態(tài)類,它沒有構(gòu)造函數(shù)缚甩,對(duì)外提供的函數(shù)也全部是靜態(tài)的谱净。其中有一個(gè)QueueUserWorkItem方法,它有兩種重載形式擅威,如下:

public static bool QueueUserWorkItem(WaitCallback callBack):將方法排入隊(duì)列以便執(zhí)行壕探。此方法在有線程池線程變得可用時(shí)執(zhí)行。

public static bool QueueUserWorkItem(WaitCallback callBack,Object state):將方法排入隊(duì)列以便執(zhí)行郊丛,并指定包含該方法所用數(shù)據(jù)的對(duì)象李请。此方法在有線程池線程變得可用時(shí)執(zhí)行瞧筛。

QueueUserWorkItem方法中使用的的WaitCallback參數(shù)表示一個(gè)delegate,它的聲明如下:

public delegate void WaitCallback(Object state)

如果需要傳遞任務(wù)信息可以利用WaitCallback中的state參數(shù)导盅,類似于ParameterizedThreadStart委托较幌。

ThreadPool 的用法:?

首先程序創(chuàng)建了一個(gè) ManualResetEvent 對(duì)象,該對(duì)象就像一個(gè)信號(hào)燈白翻,可以利用它的信號(hào)來通知其它線程绅络。

ManualResetEvent 對(duì)象有幾個(gè)重要的方法:

初始化該對(duì)象時(shí),用戶可以指定其默認(rèn)的狀態(tài)(有信號(hào)/無信號(hào))嘁字;

在初始化以后恩急,該對(duì)象將保持原來的狀態(tài)不變,直到它的 Reset() 或者 Set() 方法被調(diào)用:?

? Reset():?

? ? ? ? ? ? ?將其設(shè)置為無信號(hào)狀態(tài)纪蜒;

? Set():?

? ? ? ? ? ? ?將其設(shè)置為有信號(hào)狀態(tài)衷恭。?

? WaitOne():?

?使當(dāng)前線程掛起,直到 ManualResetEvent 對(duì)象處于有信號(hào)狀態(tài)纯续,此時(shí)該線程將被激活随珠。然后,程序?qū)⑾蚓€程池中添加工作項(xiàng)猬错,這些以函數(shù)形式提供的工作項(xiàng)被系統(tǒng)用來初始化自動(dòng)建立的線程窗看。當(dāng)所有的線程都運(yùn)行完了以后,ManualResetEvent.Set() 方法被調(diào)用倦炒,因?yàn)檎{(diào)用了 ManualResetEvent.WaitOne() 方法而處在等待狀態(tài)的主線程將接收到這個(gè)信號(hào)显沈,于是它接著往下執(zhí)行,完成后邊的工作逢唤。

我們?cè)谝粋€(gè)程序中創(chuàng)建一個(gè)線程拉讯,安排給它一個(gè)任務(wù),便交由操作系統(tǒng)來調(diào)度執(zhí)行鳖藕。操作系統(tǒng)會(huì)管理系統(tǒng)中所有的線程魔慷,并且使用一定的方式進(jìn)行調(diào)度。什么是“調(diào)度”著恩?調(diào)度便是控制線程的狀態(tài):執(zhí)行院尔,等待等等。我們都知道喉誊,從理論上來說有多少個(gè)處理單元(如2 * 2 CPU的機(jī)器便有4個(gè)處理單元)邀摆,就表示操作系統(tǒng)可以同時(shí)做幾件事情。但是線程的數(shù)量會(huì)遠(yuǎn)遠(yuǎn)超過處理單元的數(shù)量裹驰,因此操作系統(tǒng)為了保證每個(gè)線程都被執(zhí)行隧熙,就必須等一個(gè)線程在某個(gè)處理器上執(zhí)行到某個(gè)情況的時(shí)候,“換”一個(gè)新的線程來執(zhí)行幻林,這便是所謂的“上下文切換(Context Switch)”贞盯。至于造成上下文切換的原因也有多種音念,可能是某個(gè)線程的邏輯決定的,如遇上鎖躏敢,或主動(dòng)進(jìn)入休眠狀態(tài)(調(diào)用Thread.Sleep方法)闷愤,但更有可能是操作系統(tǒng)發(fā)現(xiàn)這個(gè)線程“超時(shí)”了。在操作系統(tǒng)中會(huì)定義一個(gè)“時(shí)間片(timeslice)“件余,當(dāng)發(fā)現(xiàn)一個(gè)線程執(zhí)行時(shí)間超過這個(gè)時(shí)間讥脐,便會(huì)把它撤下,換上另外一個(gè)啼器。這樣看起來旬渠,多個(gè)線程——也就是多個(gè)任務(wù)在同時(shí)運(yùn)行了。值得一提的是端壳,對(duì)于Windows操作系統(tǒng)來說告丢,它的調(diào)度單元是線程,這和線程究竟屬于哪個(gè)進(jìn)程并沒有關(guān)系损谦。

QueueUserWorkItem這個(gè)技術(shù)存在許多限制岖免。其中最大的問題是沒有一個(gè)內(nèi)建的機(jī)制讓你知道操作在什么時(shí)候完成,也沒有一個(gè)機(jī)制在操作完成時(shí)獲得一個(gè)返回值照捡,這些問題使得我們都不敢啟用這個(gè)技術(shù)颅湘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市栗精,隨后出現(xiàn)的幾起案子闯参,更是在濱河造成了極大的恐慌,老刑警劉巖术羔,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赢赊,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡级历,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門叭披,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寥殖,“玉大人,你說我怎么就攤上這事涩蜘〗拦保” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵同诫,是天一觀的道長(zhǎng)粤策。 經(jīng)常有香客問我,道長(zhǎng)误窖,這世上最難降的妖魔是什么叮盘? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任秩贰,我火速辦了婚禮,結(jié)果婚禮上柔吼,老公的妹妹穿的比我還像新娘毒费。我一直安慰自己,他們只是感情好愈魏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布觅玻。 她就那樣靜靜地躺著,像睡著了一般培漏。 火紅的嫁衣襯著肌膚如雪溪厘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天牌柄,我揣著相機(jī)與錄音畸悬,去河邊找鬼。 笑死友鼻,一個(gè)胖子當(dāng)著我的面吹牛傻昙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播彩扔,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼妆档,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了虫碉?” 一聲冷哼從身側(cè)響起贾惦,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎敦捧,沒想到半個(gè)月后须板,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兢卵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年习瑰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秽荤。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡甜奄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窃款,到底是詐尸還是另有隱情课兄,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布晨继,位于F島的核電站烟阐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜒茄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一唉擂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扩淀,春花似錦楔敌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至胜臊,卻和暖如春勺卢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背象对。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工黑忱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勒魔。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓甫煞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親冠绢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抚吠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法弟胀,內(nèi)部類的語(yǔ)法楷力,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法孵户,線程的語(yǔ)...
    子非魚_t_閱讀 31,581評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理萧朝,服務(wù)發(fā)現(xiàn),斷路器夏哭,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 這個(gè)冬天竖配,好像少雨厕吉,今天起來的時(shí)候,好不容易看到地面有些濕械念,但還不足以讓老媽放心的程度,因?yàn)樗俗讶鲈诘厣显吮L(zhǎng)不出...
    張仁女閱讀 361評(píng)論 0 0
  • 一:熟悉產(chǎn)品 1.認(rèn)真學(xué)習(xí)考察技術(shù)龄减,方便跟同行介紹我們的產(chǎn)品,容易清楚的判斷出客戶能不能做班眯,能做多少希停。 2.提升工...
    路娟娟閱讀 440評(píng)論 0 0
  • 01 我不喜歡你總是一副胸有成竹的樣子烁巫,好像我沒你不行。 可事實(shí)就是這樣宠能,只要你一找我亚隙,我立馬就不記得上一秒發(fā)過的...
    Ruueryee閱讀 561評(píng)論 0 0