newFixedThreadPool與newSingleThreadPool的區(qū)別

newFixedThreadPool與newSingleThreadPool的區(qū)別

問題引出

newFixedThreadPoolnewSingleThreadPool是jdk5之后呻右,java.util.concurrent包下Executors類中的兩個(gè)方法闷煤。前者是用于創(chuàng)建一個(gè)固定線程數(shù)量的線程池沃粗,后者是創(chuàng)建一個(gè)有且僅有一個(gè)線程的線程池绞旅。

機(jī)智的同學(xué)想必已經(jīng)看出一個(gè)問題了,一個(gè)線程不也就是固定數(shù)量的一個(gè)特例嗎宵溅,為什么還需要單獨(dú)添加一個(gè)方法呢?

第一層

二話不說,先擺上源碼别垮。
newFixedThreadPool在jdk8中的代碼如圖:


newFixedThreadPool

newSingleThreadPool在jdk8中的代碼如圖:


newSingleThreadPool

通過肉眼粗略的比較,發(fā)現(xiàn)FixPool中corePoolSizemaximumPoolSize傳入的都是nThreads扎谎,而SinglePool中傳入的都是1碳想。

這時(shí)有的人就悟了,這不就相當(dāng)于是方法的重載嘛毁靶。一個(gè)是需要傳入nThreads胧奔,而另一個(gè)就是不用傳參,默認(rèn)傳入1预吆。另外為了使用時(shí)更方便些龙填,把不傳參的這個(gè)方法給重命名了,變成更具象化的名稱newSingleThreadPool拐叉。在我看來岩遗,這也許也是設(shè)計(jì)者Doug Lea的其中之一個(gè)目的吧。

如果你也已經(jīng)看出這一點(diǎn)了凤瘦,那么恭喜你宿礁,你已經(jīng)來到了第一層

第二層

再把源碼拿出來蔬芥,重新再找找不同梆靖。這是一個(gè)找茬的游戲。


newFixedThreadPool

newSingleThreadPool

其實(shí)很多小伙伴在最開始的時(shí)候就已經(jīng)發(fā)現(xiàn)了坝茎,我們眼睛又不瞎涤姊,明顯行數(shù)不一樣,在newSingleThreadPool方法體的第一行嗤放,那么一大串的return new FinalizableDelegatedExecutorService早就看到了思喊,還以為我們看不見嗎?次酌?

巧了不是恨课,我第一次看源碼的時(shí)候,就會(huì)<b>裝作</b>看不見岳服。畢竟在閱讀源碼的時(shí)候剂公,一個(gè)我認(rèn)為比較正確的思路是只看主干,忽略掉旁枝末節(jié)吊宋,只有在確實(shí)要對(duì)某一個(gè)模塊去做深入的時(shí)候纲辽,才會(huì)去了解內(nèi)部的細(xì)節(jié)。不然一個(gè)比較大的框架源碼有幾萬幾十萬幾百萬行代碼,哪里能啃的動(dòng)拖吼。

如果你想一次性直接一行行代碼讀下去鳞上,把整個(gè)框架學(xué)習(xí)一遍,那我估計(jì)你肯定一個(gè)框架都讀不好吊档,是個(gè)普通人真的沒有這種定力篙议。

舉個(gè)例子,一個(gè)剛開始學(xué)認(rèn)字的小朋友怠硼,說‘我不認(rèn)識(shí)字呀怎么辦鬼贱?’,‘不識(shí)字查字典呀’香璃,‘懂了这难,我這就從新華字典第一頁翻起,字字句句讀到最后一頁’增显。那么這個(gè)小朋友最終是讀完字段后雁佳,學(xué)會(huì)認(rèn)字了嗎,還是永遠(yuǎn)都在讀第一頁了解[ā][á][ǎ][à]同云。

如果你能夠?qū)W會(huì)怎么什么時(shí)候該去粗讀,什么時(shí)候該去精讀堵腹,那么恭喜你炸站,已經(jīng)到達(dá)了第二層

至此疚顷,我就可以繼續(xù)往下說了旱易,也怕誤人子弟。讓看了我的文章的人腿堤,以后讀源碼時(shí)鉆牛角尖阀坏,一個(gè)勁的要看到native方法才罷休。

第三層

再翻回來細(xì)讀笆檀。作為一個(gè)正常人忌堂,直接將nThreads改寫為1不就完事了嗎,為什么還要去用FinalizableDelegatedExecutorService來封裝一遍酗洒?凡事反常必有妖士修,看看jdk大佬到底為何要做此封裝。

上類關(guān)系圖樱衷。


關(guān)系圖

其實(shí)在源碼里面直接類棋嘲,查看類的父類和實(shí)現(xiàn)的接口也很方便,不過為了在文章中能夠說清楚矩桂,還是擺出關(guān)系圖更直觀些沸移,也能省一些筆墨。

FinalizableDelegatedExecutorService的父類是DelegatedExecutorService,兩者雖然都是Executors的內(nèi)部類,DelegatedExecutorServiceThreadPoolExecutor一樣雹锣,都是繼承自AbstractExecutorService流妻。說白了他們兩是兄弟關(guān)系。

再看一樣AbstractExecutorService中實(shí)現(xiàn)的方法笆制,只有一些提交任務(wù)之類的方法绅这。而熟悉ThreadPoolExecutor的朋友都知道,內(nèi)部是有比較豐富的方法去操作線程池的核心參數(shù)的在辆。

ThreadPoolExecutor方法修改核心參數(shù)

回頭再看看DelegatedExecutorService中证薇,竟然只實(shí)現(xiàn)了任務(wù)提交、關(guān)閉等方法匆篓。

DelegatedExecutorService方法

兩者比較之下浑度,最終就可以發(fā)現(xiàn),對(duì)于FinalizableDelegatedExecutorService來說鸦概,關(guān)閉了對(duì)線程池參數(shù)的修改權(quán)限箩张,因此在使用中,不會(huì)將固定的線程數(shù)1誤修改為非1的情況窗市。防止出現(xiàn)明明設(shè)置了單個(gè)線程先慷,在使用時(shí)卻出現(xiàn)了線程池中存在多個(gè)線程的問題。

demo如下:


ThreadDemo

至此咨察,能夠看懂如此設(shè)計(jì)是為什么论熙,能實(shí)現(xiàn)什么功能。那么已經(jīng)到達(dá)了第三層摄狱。

第四層

看懂了為什么這么做脓诡,這只是術(shù),還更應(yīng)該了解法媒役。

關(guān)于‘道祝谚、法、術(shù)酣衷、器交惯、勢(shì)’的內(nèi)容可以看我其他的筆記。

法即法則鸥诽、思想商玫。了解為什么這樣設(shè)計(jì),依據(jù)的設(shè)計(jì)思想是什么牡借?學(xué)會(huì)這些才能帶你進(jìn)入更深的層次拳昌。

在我淺顯的看來,newSingleThreadPool的設(shè)計(jì)是一個(gè)典型的體現(xiàn)了單一職責(zé)原則和接口隔離原則钠龙。

此方法只能提供創(chuàng)建固定線程池的作用炬藤,職責(zé)單一御铃。

對(duì)于線程核心參數(shù)不操作的情況,通過面向?qū)ο蟮脑O(shè)計(jì)沈矿,將這些方法都隔離出去上真,沒有操作的權(quán)限。因此也體現(xiàn)了接口隔離的原則羹膳。

除了設(shè)計(jì)原則睡互,在阿里的開發(fā)規(guī)范中,是禁止我們使用Executors類去直接創(chuàng)建線程的陵像。

因?yàn)樵谧铋_始的構(gòu)造方法中我們就已經(jīng)發(fā)現(xiàn)就珠,使用的隊(duì)列是一個(gè)沒有指定大小的無界隊(duì)列,在極端情況下會(huì)出現(xiàn)oom醒颖。

所以說了這么久newSingleThreadPool的優(yōu)點(diǎn)妻怎,在實(shí)際的使用場(chǎng)景中,并用不到這里的方法泞歉。然而我們?cè)趯?shí)際工作場(chǎng)景中逼侦,多多少少在特定的業(yè)務(wù)場(chǎng)景下,要用到單線程的線程池腰耙。

工作中如果直接使用new ThreadPoolExecutor()的方式去創(chuàng)建線程池時(shí)榛丢,應(yīng)該完善文檔,提示不要去修改線程數(shù)量沟优。
更合理的方式應(yīng)該是在第四層法的指導(dǎo)下涕滋,通過一些技術(shù)手段,模仿Executors這個(gè)類挠阁,實(shí)現(xiàn)一個(gè)器即工具類,通過代碼的手段直接從根本上規(guī)避單線程池被修改線程數(shù)量而導(dǎo)致的問題溯饵。

如果也看懂了設(shè)計(jì)思想侵俗,也能夠讓這種思想指導(dǎo)以后的工作,那么說明你的學(xué)習(xí)是有用的丰刊,不再是那種自己感動(dòng)自己的行為隘谣。此刻,你已經(jīng)到達(dá)了第四層啄巧。

第五層

還沒到第五層寻歧,只能等大神們幫忙蓋樓搭梯,看看有沒有人能領(lǐng)我去第五層瞧瞧高處的風(fēng)景秩仆。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末码泛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子澄耍,更是在濱河造成了極大的恐慌噪珊,老刑警劉巖晌缘,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異痢站,居然都是意外死亡磷箕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門阵难,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岳枷,“玉大人,你說我怎么就攤上這事呜叫】辗保” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵怀偷,是天一觀的道長家厌。 經(jīng)常有香客問我,道長椎工,這世上最難降的妖魔是什么饭于? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮维蒙,結(jié)果婚禮上掰吕,老公的妹妹穿的比我還像新娘。我一直安慰自己颅痊,他們只是感情好殖熟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斑响,像睡著了一般菱属。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舰罚,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天纽门,我揣著相機(jī)與錄音,去河邊找鬼营罢。 笑死赏陵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饲漾。 我是一名探鬼主播蝙搔,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼考传!你這毒婦竟也來了吃型?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤伙菊,失蹤者是張志新(化名)和其女友劉穎败玉,沒想到半個(gè)月后敌土,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡运翼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年返干,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片血淌。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矩欠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悠夯,到底是詐尸還是另有隱情癌淮,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布沦补,位于F島的核電站乳蓄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏夕膀。R本人自食惡果不足惜虚倒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望产舞。 院中可真熱鬧魂奥,春花似錦、人聲如沸易猫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽准颓。三九已至哈蝇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間攘已,已是汗流浹背买鸽。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贯被,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓妆艘,卻偏偏與公主長得像彤灶,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子批旺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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