線程池的實(shí)現(xiàn)原理陡舅、優(yōu)點(diǎn)與風(fēng)險(xiǎn)、以及四種線程池實(shí)現(xiàn)

為什么需要線程池

我們有兩種常見(jiàn)的創(chuàng)建線程的方法伴挚,一種是繼承Thread類靶衍,一種是實(shí)現(xiàn)Runnable的接口,Thread類其實(shí)也是實(shí)現(xiàn)了Runnable接口茎芋。但是我們創(chuàng)建這兩種線程在運(yùn)行結(jié)束后都會(huì)被虛擬機(jī)銷毀颅眶,如果線程數(shù)量多的話,頻繁的創(chuàng)建和銷毀線程會(huì)大大浪費(fèi)時(shí)間和效率田弥,更重要的是浪費(fèi)內(nèi)存涛酗。那么有沒(méi)有一種方法能讓線程運(yùn)行完后不立即銷毀,而是讓線程重復(fù)使用偷厦,繼續(xù)執(zhí)行其他的任務(wù)哪商叹?

這就是線程池的由來(lái),很好的解決線程的重復(fù)利用只泼,避免重復(fù)開(kāi)銷剖笙。

線程池的優(yōu)點(diǎn)

1、線程是稀缺資源辜妓,使用線程池可以減少創(chuàng)建和銷毀線程的次數(shù)枯途,每個(gè)工作線程都可以重復(fù)使用忌怎。

2、可以根據(jù)系統(tǒng)的承受能力酪夷,調(diào)整線程池中工作線程的數(shù)量榴啸,防止因?yàn)橄倪^(guò)多內(nèi)存導(dǎo)致服務(wù)器崩潰。

線程池的風(fēng)險(xiǎn)

雖然線程池是構(gòu)建多線程應(yīng)用程序的強(qiáng)大機(jī)制晚岭,但使用它并不是沒(méi)有風(fēng)險(xiǎn)的鸥印。用線程池構(gòu)建的應(yīng)用程序容易遭受任何其它多線程應(yīng)用程序容易遭受的所有并發(fā)風(fēng)險(xiǎn),諸如同步錯(cuò)誤和死鎖坦报,它還容易遭受特定于線程池的少數(shù)其它風(fēng)險(xiǎn)库说,諸如與池有關(guān)的死鎖、資源不足和線程泄漏片择。

1.死鎖

任何多線程應(yīng)用程序都有死鎖風(fēng)險(xiǎn)潜的。當(dāng)一組進(jìn)程或線程中的每一個(gè)都在等待一個(gè)只有該組中另一個(gè)進(jìn)程才能引起的事件時(shí),我們就說(shuō)這組進(jìn)程或線程?死鎖了字管。死鎖的最簡(jiǎn)單情形是:線程 A 持有對(duì)象 X 的獨(dú)占鎖啰挪,并且在等待對(duì)象 Y 的鎖,而線程 B 持有對(duì)象 Y 的獨(dú)占鎖嘲叔,卻在等待對(duì)象 X 的鎖亡呵。除非有某種方法來(lái)打破對(duì)鎖的等待(Java 鎖定不支持這種方法),否則死鎖的線程將永遠(yuǎn)等下去硫戈。

2.資源不足

線程池的一個(gè)優(yōu)點(diǎn)在于:相對(duì)于其它替代調(diào)度機(jī)制(有些我們已經(jīng)討論過(guò))而言锰什,它們通常執(zhí)行得很好。但只有恰當(dāng)?shù)卣{(diào)整了線程池大小時(shí)才是這樣的丁逝。

線程消耗包括內(nèi)存和其它系統(tǒng)資源在內(nèi)的大量資源汁胆。除了

Thread 對(duì)象所需的內(nèi)存之外,每個(gè)線程都需要兩個(gè)可能很大的執(zhí)行調(diào)用堆棧果港。除此以外沦泌,JVM 可能會(huì)為每個(gè) Java

線程創(chuàng)建一個(gè)本機(jī)線程糊昙,這些本機(jī)線程將消耗額外的系統(tǒng)資源辛掠。最后,雖然線程之間切換的調(diào)度開(kāi)銷很小释牺,但如果有很多線程萝衩,環(huán)境切換也可能嚴(yán)重地影響程序的性能。

如果線程池太大没咙,那么被那些線程消耗的資源可能嚴(yán)重地影響系統(tǒng)性能猩谊。在線程之間進(jìn)行切換將會(huì)浪費(fèi)時(shí)間,而且使用超出比您實(shí)際需要的線程可能會(huì)引起資源匱乏問(wèn)題祭刚,因?yàn)槌鼐€程正在消耗一些資源牌捷,而這些資源可能會(huì)被其它任務(wù)更有效地利用墙牌。

除了線程自身所使用的資源以外,服務(wù)請(qǐng)求時(shí)所做的工作可能需要其它資源暗甥,例如 JDBC 連接喜滨、套接字或文件,這些也都是有限資源撤防,有太多的并發(fā)請(qǐng)求也可能引起失效虽风,例如不能分配 JDBC 連接。

3.并發(fā)錯(cuò)誤

線程池和其它排隊(duì)機(jī)制依靠使用

wait() 和 notify()

方法寄月,這兩個(gè)方法都難于使用辜膝。如果編碼不正確,那么可能丟失通知漾肮,導(dǎo)致線程保持空閑狀態(tài)厂抖,盡管隊(duì)列中有工作要處理。使用這些方法時(shí)克懊,必須格外小心验游;即便是專家也可能在它們上面出錯(cuò)。而最好使用現(xiàn)有的保檐、已經(jīng)知道能工作的實(shí)現(xiàn)耕蝉,例如在

util.concurrent 包。

4.線程泄漏

各種類型的線程池中一個(gè)嚴(yán)重的風(fēng)險(xiǎn)是線程泄漏夜只,當(dāng)從池中除去一個(gè)線程以執(zhí)行一項(xiàng)任務(wù)垒在,而在任務(wù)完成后該線程卻沒(méi)有返回池時(shí),會(huì)發(fā)生這種情況扔亥。發(fā)生線程泄漏的一種情形出現(xiàn)在任務(wù)拋出一個(gè) RuntimeException 或一個(gè) Error 時(shí)场躯。

如果池類沒(méi)有捕捉到它們,那么線程只會(huì)退出而線程池的大小將會(huì)永久減少一個(gè)旅挤。當(dāng)這種情況發(fā)生的次數(shù)足夠多時(shí)踢关,線程池最終就為空,而且系統(tǒng)將停止粘茄,因?yàn)闆](méi)有可用的線程來(lái)處理任務(wù)签舞。

5.請(qǐng)求過(guò)載

僅僅是請(qǐng)求就壓垮了服務(wù)器,這種情況是可能的柒瓣。在這種情形下儒搭,我們可能不想將每個(gè)到來(lái)的請(qǐng)求都排隊(duì)到我們的工作隊(duì)列,因?yàn)榕旁陉?duì)列中等待執(zhí)行的任務(wù)可能會(huì)消耗太多的系統(tǒng)資源并引起資源缺乏芙贫。在這種情形下決定如何做取決于您自己搂鲫;在某些情況下,您可以簡(jiǎn)單地拋棄請(qǐng)求磺平,依靠更高級(jí)別的協(xié)議稍后重試請(qǐng)求魂仍,您也可以用一個(gè)指出服務(wù)器暫時(shí)很忙的響應(yīng)來(lái)拒絕請(qǐng)求拐辽。

線程池的實(shí)現(xiàn)原理

線程池

1.線程池狀態(tài)

線程池和線程一樣擁有自己的狀態(tài),在ThreadPoolExecutor類中定義了一個(gè)volatile變量runState來(lái)表示線程池的狀態(tài)擦酌,線程池有四種狀態(tài)薛训,分別為RUNNING、SHURDOWN仑氛、STOP乙埃、TERMINATED。

?線程池創(chuàng)建后處于RUNNING狀態(tài)锯岖。

?調(diào)用shutdown后處于SHUTDOWN狀態(tài)介袜,線程池不能接受新的任務(wù),會(huì)等待緩沖隊(duì)列的任務(wù)完成出吹。

?調(diào)用shutdownNow后處于STOP狀態(tài)遇伞,線程池不能接受新的任務(wù),并嘗試終止正在執(zhí)行的任務(wù)捶牢。

?當(dāng)線程池處于SHUTDOWN或STOP狀態(tài)鸠珠,并且所有工作線程已經(jīng)銷毀,任務(wù)緩存隊(duì)列已經(jīng)清空或執(zhí)行結(jié)束后秋麸,線程池被設(shè)置為T(mén)ERMINATED狀態(tài)渐排。

線程池原理:預(yù)先啟動(dòng)一些線程,線程無(wú)限循環(huán)從任務(wù)隊(duì)列中獲取一個(gè)任務(wù)進(jìn)行執(zhí)行灸蟆,直到線程池被關(guān)閉驯耻。如果某個(gè)線程因?yàn)閳?zhí)行某個(gè)任務(wù)發(fā)生異常而終止,那么重新創(chuàng)建一個(gè)新的線程而已炒考,如此反復(fù)可缚。

2.線程池的處理流程

1、判斷線程池里的核心線程是否都在執(zhí)行任務(wù)斋枢,如果不是(核心線程空閑或者還有核心線程沒(méi)有被創(chuàng)建)則創(chuàng)建一個(gè)新的工作線程來(lái)執(zhí)行任務(wù)帘靡。如果核心線程都在執(zhí)行任務(wù),則進(jìn)入下個(gè)流程瓤帚。

2描姚、線程池判斷工作隊(duì)列是否已滿,如果工作隊(duì)列沒(méi)有滿缘滥,則將新提交的任務(wù)存儲(chǔ)在這個(gè)工作隊(duì)列里轰胁。如果工作隊(duì)列滿了,則進(jìn)入下個(gè)流程朝扼。

3、判斷線程池里的線程是否都處于工作狀態(tài)霎肯,如果沒(méi)有擎颖,則創(chuàng)建一個(gè)新的工作線程來(lái)執(zhí)行任務(wù)榛斯。如果已經(jīng)滿了,則交給飽和策略來(lái)處理這個(gè)任務(wù)搂捧。

配置線程池大小配置

一般需要根據(jù)任務(wù)的類型來(lái)配置線程池大型运住:

如果是CPU密集型任務(wù),就需要盡量壓榨CPU允跑,參考值可以設(shè)為?NCPU+1

如果是IO密集型任務(wù)王凑,參考值可以設(shè)置為2*NCPU

當(dāng)然,這只是一個(gè)參考值聋丝,具體的設(shè)置還需要根據(jù)實(shí)際情況進(jìn)行調(diào)整索烹,比如可以先將線程池大小設(shè)置為參考值,再觀察任務(wù)運(yùn)行情況和系統(tǒng)負(fù)載弱睦、資源利用率來(lái)進(jìn)行適當(dāng)調(diào)整百姓。

Java提供的四種線程池實(shí)現(xiàn)

(1)newCachedThreadPool創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要况木,可靈活回收空閑線程垒拢,若無(wú)可回收,則新建線程火惊。

(2)newFixedThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池求类,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待屹耐。

(3)newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線程池仑嗅,支持定時(shí)及周期性任務(wù)執(zhí)行。

(4)newSingleThreadExecutor 創(chuàng)建一個(gè)單線程化的線程池张症,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù)仓技,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級(jí))執(zhí)行。

以上就是線程池的詳細(xì)介紹俗他,后續(xù)將詳細(xì)講解四種線程池的具體實(shí)現(xiàn)脖捻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市兆衅,隨后出現(xiàn)的幾起案子地沮,更是在濱河造成了極大的恐慌,老刑警劉巖羡亩,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件摩疑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡畏铆,警方通過(guò)查閱死者的電腦和手機(jī)雷袋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)辞居,“玉大人楷怒,你說(shuō)我怎么就攤上這事蛋勺。” “怎么了鸠删?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵抱完,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我刃泡,道長(zhǎng)巧娱,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任烘贴,我火速辦了婚禮禁添,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘庙楚。我一直安慰自己上荡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布馒闷。 她就那樣靜靜地躺著酪捡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪纳账。 梳的紋絲不亂的頭發(fā)上逛薇,一...
    開(kāi)封第一講書(shū)人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音疏虫,去河邊找鬼永罚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卧秘,可吹牛的內(nèi)容都是我干的呢袱。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼翅敌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼羞福!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蚯涮,我...
    開(kāi)封第一講書(shū)人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤治专,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后遭顶,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體张峰,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年棒旗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喘批。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖谤祖,靈堂內(nèi)的尸體忽然破棺而出婿滓,到底是詐尸還是另有隱情老速,我是刑警寧澤粥喜,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站橘券,受9級(jí)特大地震影響额湘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旁舰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一锋华、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧箭窜,春花似錦毯焕、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至竹捉,卻和暖如春芜辕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背块差。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工侵续, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憨闰。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓状蜗,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親鹉动。 傳聞我的和親對(duì)象是個(gè)殘疾皇子轧坎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350