Executor框架淺析

59d4b4335035dc06f54f78dcdf30994c.png

1 為什么需要線程池掷贾?

  • 1.在java中睛榄,使用線程來執(zhí)行異步任務(wù)時(shí),線程的創(chuàng)建和銷毀需要一定的開銷想帅。如果我們?yōu)槊恳粋€(gè)任務(wù)創(chuàng)建一個(gè)新的線程來執(zhí)行的話场靴,那么這些線程的創(chuàng)建與銷毀將消耗大量的計(jì)算資源。
  • 2.為每一個(gè)任務(wù)創(chuàng)建一個(gè)新線程來執(zhí)行港准,這樣的方式可能會(huì)使處于高負(fù)荷狀態(tài)的應(yīng)用最終崩潰旨剥。
  • 曙光我們將在線程池中創(chuàng)建若干條線程,當(dāng)有任務(wù)需要執(zhí)行時(shí)就從該線程池中獲取一條線程來執(zhí)行任務(wù)浅缸,如果一時(shí)間任務(wù)過多轨帜,超出線程池的線程數(shù)量,那么后面的線程任務(wù)就進(jìn)入一個(gè)等待隊(duì)列進(jìn)行等待衩椒,直到線程池有線程處于空閑時(shí)才從等待隊(duì)列獲取要執(zhí)行的任務(wù)進(jìn)行處理蚌父,以此循環(huán).....這樣就大大減少了線程創(chuàng)建和銷毀的開銷,也會(huì)緩解我們的應(yīng)用處于超負(fù)荷時(shí)的情況毛萌。

2 Executor框架的兩級(jí)調(diào)度模型

  • 在java線程啟動(dòng)時(shí)會(huì)創(chuàng)建一個(gè)本地操作系統(tǒng)線程苟弛,當(dāng)該java線程終止時(shí),這個(gè)操作系統(tǒng)線程也會(huì)被回收朝聋。
  • 每一個(gè)java線程都會(huì)被一對(duì)一映射為本地操作系統(tǒng)的線程嗡午,操作系統(tǒng)會(huì)調(diào)度所有的線程并將它們分別給可用的CPU。
  • 所謂的映射方式是這樣實(shí)現(xiàn)的冀痕,在上層荔睹,java多線程程序通過把應(yīng)用分為若干個(gè)任務(wù)狸演,然后使用用戶級(jí)的調(diào)度器(Executor框架)將這些任務(wù)映射為固定數(shù)量的線程;在底層僻他,操作系統(tǒng)內(nèi)核將這些線程映射到硬件處理器上宵距。
f45f7178da7d06f10b493211ce44ff12.png

從圖中我們可以看出,應(yīng)用程序通過Executor框架控制上層的調(diào)度吨拗,而下層的調(diào)度由操作系統(tǒng)內(nèi)核控制满哪,下層的調(diào)度不受應(yīng)用程序的控制。

3 Executor框架的結(jié)構(gòu)

Executor框架的結(jié)構(gòu)主要包括3個(gè)部分

  • 1.任務(wù):包括被執(zhí)行任務(wù)需要實(shí)現(xiàn)的接口:Runnable接口或Callable接口
  • 2.任務(wù)的執(zhí)行:包括任務(wù)執(zhí)行機(jī)制的核心接口Executor劝篷,以及繼承自Executor的EexcutorService接口哨鸭。Exrcutor有兩個(gè)關(guān)鍵類實(shí)現(xiàn)了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)。
  • 3.異步計(jì)算的結(jié)果:包括接口Future和實(shí)現(xiàn)Future接口的FutureTask類

4 類間的關(guān)系UML

fcbe284d0c2f25ddda8dc084a6ddd984.png
  • Extecutor是一個(gè)接口娇妓,它是Executor框架的基礎(chǔ)像鸡,它將任務(wù)的提交與任務(wù)的執(zhí)行分離開來
  • ThreadPoolExecutor是線程池的核心實(shí)現(xiàn)類哈恰,用來執(zhí)行被提交的任務(wù)只估。
  • ScheduledThreadPoolExecutor是一個(gè)實(shí)現(xiàn)類,可以在給定的延遲后運(yùn)行命令着绷,或者定期執(zhí)行命令蛔钙。ScheduledThreadPoolExecutor比Timer更靈活,功能更強(qiáng)大荠医。
  • Future接口和實(shí)現(xiàn)Future接口的FutureTask類吁脱,代表異步計(jì)算的結(jié)果
  • Runnable接口和Callable接口的實(shí)現(xiàn)類子漩,都可以被ThreadPoolExecutor或者ScheduledThreadPoolExecutor執(zhí)行豫喧。區(qū)別就是Runnable無法返回執(zhí)行結(jié)果,而Callable可以返回執(zhí)行結(jié)果幢泼。

5 執(zhí)行關(guān)系

1e9bb20e57e04cc636953dca39ee0fd8.png

分析說明

  • 創(chuàng)建任務(wù)對(duì)象
    主線程首先創(chuàng)建實(shí)現(xiàn)Runnable或Callable接口的任務(wù)對(duì)象紧显,工具類Executors可以把一個(gè)Runnable對(duì)象封裝為一個(gè)Callable對(duì)象,使用如下兩種方式:
Executors.callable(Runnable task)或者Executors.callable(Runnable task,Object resule)。
  • 執(zhí)行任務(wù)
    把Runnable對(duì)象直接提交給ExecutorService執(zhí)行缕棵,方法為ExecutorService.execute(Runnable command)孵班;
    把Runnable對(duì)象或者Callable對(duì)象提交給ExecutorService執(zhí)行,方法為ExecutorService.submit(Runnable task)或ExecutorService.submit(Callable task)招驴。
  • 注意的是如果執(zhí)行ExecutorService.submit(...),ExecutorService將返回一個(gè)實(shí)現(xiàn)Future接口的對(duì)象(其實(shí)就是FutureTask)篙程。

當(dāng)然由于FutureTask實(shí)現(xiàn)了Runnable接口,我們也可以直接創(chuàng)建FutureTask别厘,然后提交給ExecutorService執(zhí)行虱饿。

6 ExecutorService任務(wù)周期管理接口

  • Java里面線程池的頂級(jí)接口是Executor,但是嚴(yán)格意義上講Executor并不是一個(gè)線程池,而只是一個(gè)執(zhí)行線程的工具氮发。
  • 真正的線程池接口是ExecutorService渴肉。
  • Executors類,提供了一系列工廠方法用于創(chuàng)先線程池爽冕,返回的線程池都實(shí)現(xiàn)了ExecutorService接口仇祭。
  • Executor的實(shí)現(xiàn)通常都會(huì)創(chuàng)建線程來執(zhí)行任務(wù),但是使用異步方式來執(zhí)行任務(wù)時(shí)颈畸,由于之前提交任務(wù)的狀態(tài)不是立即可見的乌奇,所以如果要關(guān)閉應(yīng)用程序時(shí),就需要將受影響的任務(wù)狀態(tài)反饋給應(yīng)用程序眯娱。
  • 為了解決執(zhí)行服務(wù)的生命周期問題礁苗,Executor擴(kuò)展了EecutorService接口,添加了一些用于生命周期管理的方法困乒。如下:
public interface ExecutorService extends Executor {    
    void shutdown();    
    List shutdownNow();    
    boolean isShutdown();    
    boolean isTerminated();    
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;    
    // 省略部分方法    
}   

參考

https://juejin.im/entry/57ad83932e958a005442862c
https://juejin.im/entry/582185c42e958a0054feccfb

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寂屏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子娜搂,更是在濱河造成了極大的恐慌,老刑警劉巖吱抚,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件百宇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡秘豹,警方通過查閱死者的電腦和手機(jī)携御,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來既绕,“玉大人啄刹,你說我怎么就攤上這事∑喾罚” “怎么了誓军?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長疲扎。 經(jīng)常有香客問我昵时,道長,這世上最難降的妖魔是什么椒丧? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任壹甥,我火速辦了婚禮,結(jié)果婚禮上壶熏,老公的妹妹穿的比我還像新娘句柠。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布溯职。 她就那樣靜靜地躺著精盅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缸榄。 梳的紋絲不亂的頭發(fā)上渤弛,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音甚带,去河邊找鬼她肯。 笑死鹰贵,一個(gè)胖子當(dāng)著我的面吹牛晴氨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播碉输,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼籽前,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了敷钾?” 一聲冷哼從身側(cè)響起枝哄,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阻荒,沒想到半個(gè)月后挠锥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侨赡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年蓖租,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羊壹。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蓖宦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出油猫,到底是詐尸還是另有隱情稠茂,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布眨攘,位于F島的核電站主慰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏鲫售。R本人自食惡果不足惜共螺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望情竹。 院中可真熱鬧藐不,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挑秉,卻和暖如春法梯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背犀概。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工立哑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人姻灶。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓铛绰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親产喉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捂掰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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