線程池的幾種實現(xiàn)方式

Executor框架最核心的類是ThreadPoolExecutor,它是線程池的實現(xiàn)類再愈,主要由下列4個組件構(gòu)成缰泡。

????·corePool:核心線程池的大小。

????·maximumPool:最大線程池的大小明肮。

????·BlockingQueue:用來暫時保存任務(wù)的工作隊列。

????·RejectedExecutionHandler:當(dāng)ThreadPoolExecutor已經(jīng)關(guān)閉或ThreadPoolExecutor已經(jīng)飽和時(達到了最大線程池大小且工作隊列已滿)缭付,execute()方法將要調(diào)用的Handler柿估。

通過Executor框架的工具類Executors,可以創(chuàng)建3種類型的ThreadPoolExecutor陷猫。

????·FixedThreadPool秫舌。

????·SingleThreadExecutor。

????·CachedThreadPool烙丛。?

下面將分別介紹這3種ThreadPoolExecutor。

FixedThreadPool被稱為可重用固定線程數(shù)的線程池羔味。下面是FixedThreadPool的源代碼實現(xiàn)河咽。

public?static?ExecutorService?newFixedThreadPool(int?nThreads)?{?

????return?new?ThreadPoolExecutor(nThreads,nThreads,

????0L,?TimeUnit.MILLISECONDS,new?LinkedBlockingQueue());

}

FixedThreadPool的corePoolSize和maximumPoolSize都被設(shè)置為創(chuàng)建FixedThreadPool時指定的參數(shù)nThreads。當(dāng)線程池中的線程數(shù)大于corePoolSize時赋元,keepAliveTime為多余的空閑線程等待新任務(wù)的最長時間忘蟹,超過這個時間后多余的線程將被終止。這里把keepAliveTime設(shè)置為0L搁凸,意味著多余的空閑線程會被立即終止媚值。

FixedThreadPool的execute()方法的運行示意圖如圖所示。

FixedThreadPool的execute()的運行示意圖

上圖的說明如下护糖。

????1)如果當(dāng)前運行的線程數(shù)少于corePoolSize褥芒,則創(chuàng)建新線程來執(zhí)行任務(wù)。

????2)在線程池完成預(yù)熱之后(當(dāng)前運行的線程數(shù)等于corePoolSize)嫡良,將任務(wù)加入?LinkedBlockingQueue锰扶。

????3)線程執(zhí)行完1中的任務(wù)后,會在循環(huán)中反復(fù)從LinkedBlockingQueue獲取任務(wù)來執(zhí)行寝受。

FixedThreadPool使用無界隊列LinkedBlockingQueue作為線程池的工作隊列(隊列的容量為?Integer.MAX_VALUE)坷牛。使用無界隊列作為工作隊列會對線程池帶來如下影響。

????1)當(dāng)線程池中的線程數(shù)達到corePoolSize后很澄,新任務(wù)將在無界隊列中等待京闰,因此線程池中的線程數(shù)不會超過? ?????corePoolSize颜及。

????2)由于1,使用無界隊列時maximumPoolSize將是一個無效參數(shù)蹂楣。?

????3)由于1和2俏站,使用無界隊列時keepAliveTime將是一個無效參數(shù)。

????4)由于使用無界隊列乾翔,運行中的FixedThreadPool(未執(zhí)行方法shutdown()或?shutdownNow())不會拒絕任務(wù)? ?(不會調(diào)用RejectedExecutionHandler.rejectedExecution方法)。

SingleThreadExecutor詳解

SingleThreadExecutor是使用單個worker線程的Executor施戴。下面是SingleThreadExecutor的源代碼實現(xiàn)。

public?static?ExecutorService?newSingleThreadExecutor()?{?

????return?new?FinalizableDelegatedExecutorService(new?ThreadPoolExecutor(1,?1,0L,?TimeUnit.MILLISECONDS????,new?LinkedBlockingQueue()));

}

SingleThreadExecutor的corePoolSize和maximumPoolSize被設(shè)置為1赞哗。其他參數(shù)與?FixedThreadPool相同。SingleThreadExecutor使用無界隊列LinkedBlockingQueue作為線程池的工作隊列(隊列的容量為Integer.MAX_VALUE)肪笋。SingleThreadExecutor使用無界隊列作為工作隊列對線程池帶來的影響與FixedThreadPool相同月劈,這里就不贅述了。

SingleThreadExecutor的運行示意圖如圖所示藤乙。

SingleThreadExecutor的execute()的運行示意

對上圖的說明如下猜揪。

????1)如果當(dāng)前運行的線程數(shù)少于corePoolSize(即線程池中無運行的線程)坛梁,則創(chuàng)建一個新線程來執(zhí)行任務(wù)而姐。

????2)在線程池完成預(yù)熱之后(當(dāng)前線程池中有一個運行的線程)划咐,將任務(wù)加入Linked-?BlockingQueue拴念。

????3)線程執(zhí)行完1中的任務(wù)后,會在一個無限循環(huán)中反復(fù)從LinkedBlockingQueue獲取任務(wù)來執(zhí)行褐缠。

CachedThreadPool詳解

CachedThreadPool是一個會根據(jù)需要創(chuàng)建新線程的線程池政鼠。下面是創(chuàng)建CachedThreadPool的源代碼。

public?static?ExecutorService?newCachedThreadPool()?{ ????return?new?ThreadPoolExecutor(0,?Integer.MAX_VALUE,

????60L,?TimeUnit.SECONDS,new?SynchronousQueue());

}

CachedThreadPool的corePoolSize被設(shè)置為0公般,即corePool為空;maximumPoolSize被設(shè)置為?Integer.MAX_VALUE胡桨,即maximumPool是無界的。這里把keepAliveTime設(shè)置為60L登失,意味著?CachedThreadPool中的空閑線程等待新任務(wù)的最長時間為60秒,空閑線程超過60秒后將會被終止揽浙。

FixedThreadPool和SingleThreadExecutor使用無界隊列LinkedBlockingQueue作為線程池的工作隊列状婶。CachedThreadPool使用沒有容量的SynchronousQueue作為線程池的工作隊列,但?CachedThreadPool的maximumPool是無界的膛虫。這意味著,如果主線程提交任務(wù)的速度高于?maximumPool中線程處理任務(wù)的速度時稍刀,CachedThreadPool會不斷創(chuàng)建新線程撩独。極端情況下账月,?CachedThreadPool會因為創(chuàng)建過多線程而耗盡CPU和內(nèi)存資源综膀。

CachedThreadPool的execute()方法的執(zhí)行示意圖如圖所示局齿。

對上圖的說明如下剧劝。

????1)首先執(zhí)行SynchronousQueue.offer(Runnable?task)抓歼。如果當(dāng)前maximumPool中有空閑線程正在執(zhí)行? ?????SynchronousQueue.poll(keepAliveTime讥此,TimeUnit.NANOSECONDS)谣妻,那么主線程執(zhí)行offer操作與空閑線? ?????程執(zhí)行的poll操作配對成功萄喳,主線程把任務(wù)交給空閑線程執(zhí)行蹋半,execute()方法執(zhí)行完成他巨;否則執(zhí)行下面的步驟

????2)當(dāng)初始maximumPool為空湃窍,或者maximumPool中當(dāng)前沒有空閑線程時闻蛀,將沒有線程執(zhí)? ?????行?SynchronousQueue.poll(keepAliveTime您市,TimeUnit.NANOSECONDS)役衡。這種情況下茵休,步驟1)將失敗手蝎。? ?????此時CachedThreadPool會創(chuàng)建一個新線程執(zhí)行任務(wù)榕莺,execute()方法執(zhí)行完成棵介。

????3)在步驟2)中新創(chuàng)建的線程將任務(wù)執(zhí)行完后钉鸯,會執(zhí)行?SynchronousQueue.poll(keepAliveTime,? ?????TimeUnit.NANOSECONDS)邮辽。這個poll操作會讓空閑線程最多在SynchronousQueue中等待60秒鐘唠雕。如果60? ?????秒鐘內(nèi)主線程提交了一個新任務(wù)(主線程執(zhí)行步驟1))贸营,那么這個空閑線程將執(zhí)行主線程提交的新任務(wù);否? ?????則岩睁,這個空閑線程將終止钞脂。由于空閑60秒的空閑線程會被終止,因此長時間保持空閑的CachedThreadPool不? ? ????會使用任何資源捕儒。

前面提到過冰啃,SynchronousQueue是一個沒有容量的阻塞隊列。每個插入操作必須等待另一個線程的對應(yīng)移除操作刘莹,反之亦然阎毅。CachedThreadPool使用SynchronousQueue,把主線程提交的任務(wù)傳遞給空閑線程執(zhí)行栋猖。CachedThreadPool中任務(wù)傳遞的示意圖如圖所示净薛。

CachedThreadPool的任務(wù)傳遞示意圖?
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蒲拉,隨后出現(xiàn)的幾起案子肃拜,更是在濱河造成了極大的恐慌,老刑警劉巖雌团,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異锦援,居然都是意外死亡,警方通過查閱死者的電腦和手機灵寺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毁枯,“玉大人,你說我怎么就攤上這事叮称。” “怎么了瓤檐?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祭示。 經(jīng)常有香客問我,道長质涛,這世上最難降的妖魔是什么悄窃? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任蹂窖,我火速辦了婚禮,結(jié)果婚禮上瞬测,老公的妹妹穿的比我還像新娘。我一直安慰自己月趟,他們只是感情好灯蝴,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布孝宗。 她就那樣靜靜地躺著,像睡著了一般因妇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婚被,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音址芯,去河邊找鬼。 笑死谷炸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的旬陡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼季惩,長吁一口氣:“原來是場噩夢啊……” “哼腻格!你這毒婦竟也來了画拾?” 一聲冷哼從身側(cè)響起菜职,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎酬核,沒想到半個月后适室,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡捣辆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年此迅,在試婚紗的時候發(fā)現(xiàn)自己被綠了汽畴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耸序。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖坎怪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搅窿,我是刑警寧澤嘁酿,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布男应,位于F島的核電站,受9級特大地震影響殉了,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜薪铜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望隔箍。 院中可真熱鬧,春花似錦蜒滩、人聲如沸滨达。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽竹握。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谓传,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工续挟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诗祸。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像贬媒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子际乘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

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