第二十二章立美、Java通過Executors提供五種線程池

Executors目前提供了5中不同的線程池創(chuàng)建配置:

1、newCachedThreadPool():它是一種用來處理大量短時間工作任務(wù)的線程池方灾,具有幾個鮮明特點:它會試圖緩存線程并重用建蹄,當午緩存線程可用時,就會創(chuàng)建新的工作線程裕偿;如果線程閑置的時間超過60秒洞慎,則被終止并移出緩存;長時間閑置時嘿棘,這種線程池劲腿,不會消耗什么資源。其內(nèi)部使用SynchronousQueue作為工作隊列蔫巩;

2谆棱、newFixedThreadPool(int nThreads)快压,重用指定數(shù)目(nThreads)的線程圆仔,其背后使用的時無界的工作隊列,任何時候最多有nThreads個工作線程時活動的蔫劣。如果任務(wù)數(shù)量超過了活動隊列數(shù)目坪郭,將在工作隊列中等待空閑線程出現(xiàn);如果有工作線程退出脉幢,將會有新的工作線程被創(chuàng)建歪沃,以補足指定的數(shù)目nThreads;

3嫌松、newSingleThreadExecutor()沪曙,它的特點在于工作線程數(shù)目被限制為1,操作一個無界的工作隊列萎羔,所以它保證了所有任務(wù)都是被順序執(zhí)行液走,最多會有一個任務(wù)處于活動狀態(tài),并且不允許使用者改動線程池實例贾陷,因此可以避免其改變線程數(shù)目缘眶;

4、newSingleThreadScheduleExecutor()和newScheduledThreadPool(int corePoolSize)髓废,創(chuàng)建的時個ScheduledExecutorService巷懈,可以進行定時或周期性的工作調(diào)度,區(qū)別在于單一工作線程還是多個工作線程慌洪;

5顶燕、newWorkStealingPool(int parallelism)凑保,這時一個經(jīng)常被人忽略的線程池,JAVA8才加入這個創(chuàng)建方法涌攻,其內(nèi)部會構(gòu)建ForkJoinPool愉适,利用Work-Stealing算法,并行地處理任務(wù)癣漆,不保證處理順序维咸。


Executor框架的基本組成

各個類型的設(shè)計目的

1、Executor是一個基礎(chǔ)的接口惠爽,其初衷是將任務(wù)提交和任務(wù)執(zhí)行細節(jié)解耦癌蓖,這一點可以天匯其定義的唯一方法。

  void execute(Runnable command);

2婚肆、ExecutorService則更加完善租副,不僅提供service管理,比如shutdown等方法较性,也提供了更加全面的提交任務(wù)機制用僧,如返回Future而不是 void 的 submit 方法

  <T> Future<T> submit(Callable<T> task);

注意,這個例子輸入的可是Callable赞咙,它解決了Runnable無法返回結(jié)果的困擾责循。

3、Java標準類庫提供了幾種基礎(chǔ)實現(xiàn)攀操,比如?ThreadPoolExecutor院仿、ScheduledThreadPoolExecutor、ForkJoinPool速和。這些線程池設(shè)的設(shè)計特點在于其高度的可調(diào)節(jié)性和靈活性歹垫,以盡量滿足復(fù)雜多變的實際應(yīng)用場景,我會進一步分析其構(gòu)建部分的源碼颠放,剖析這種靈活性的源頭排惨。

4、Executors則從簡化使用的角度碰凶,為我們提供了各種方便的靜態(tài)工長方法暮芭。

阿里發(fā)布的 Java開發(fā)手冊中強制線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式痒留,這樣的處理方式讓寫的同學(xué)更加明確線程池的運行規(guī)則谴麦,規(guī)避資源耗盡的風(fēng)險

下面從源碼角度,分析線程池的設(shè)計與實現(xiàn)伸头,將主要圍繞最基礎(chǔ)的ThreadPoolExecutor源碼匾效。ScheduledThreadPoolExecutor是ThreadPoolExecutor的擴展,主要是增加了調(diào)度邏輯恤磷。而ForkJoinPool則是為了ForkJoinTask定制的線程池面哼,與通常意義的線程池有所不同野宜。

在現(xiàn)實應(yīng)用中,理解應(yīng)用于線程池的交互和線程池內(nèi)部的工作過程魔策,可以參考下圖匈子。


?簡單理解一下:

1、工作隊列負責(zé)存儲用戶提交的各個任務(wù)闯袒,這個工作隊列虎敦,可以是容量為0的 SynchronousQueue(使用newCachedThreadPool),也可以是像固定大小線程池(newFixedThreadPool)那樣使用LinkedBlockingQueue政敢。

  private final BlockingQueue<Runnable> workQueue;

2其徙、內(nèi)部的“線程池”,這是指保持工作線程的集合喷户,線程池需要在運行過程中管理線程創(chuàng)建唾那、銷毀。例如褪尝,對于帶緩存的線程池闹获,當任務(wù)壓力較大時,線程池會創(chuàng)建新的工作線程河哑;當業(yè)務(wù)壓力退去避诽,線程池會閑置一段時間(默認60秒)后結(jié)束線程。

  private final HashSet<Worker> workers = new HashSet<Worker>();

  線程池的工作線程被抽象為靜態(tài)內(nèi)部類Worker灾馒,基于AQS實現(xiàn)

3茎用、ThreadFactory提供上面所需要的創(chuàng)建線程邏輯遣总。

4睬罗、如果任務(wù)提交時被拒絕,比如線程池已處于SHUTDOWN狀態(tài)旭斥,需要為其提供處理邏輯容达,Java 標準庫提供了類似?ThreadPoolExecutor.AbortPolicy 等默認實現(xiàn),也可以按照實際需要自定義垂券。

從上面的分析花盐,就可以看出線程池的幾個基本組成部分,一起都體現(xiàn)在線程池的構(gòu)造函數(shù)中菇爪,從字面我們就可以猜測到其用意:

1算芯、corePoolSize, 稍微的核心線程數(shù),可以大致理解為長期駐留的線程數(shù)目(除非設(shè)置了allowCoreThreadTimeOut)凳宙。對于不同的線程池熙揍,這個值可能會有很大區(qū)別,比如newFixedThreadPool 會將其設(shè)置為 nThreads 氏涩,而對于newCachedThreadPool則設(shè)為0届囚。

2有梆、maximumPoolSize,顧名思義意系,就是線程不夠時能夠創(chuàng)建的最大線程數(shù)泥耀。同樣進行對比,對于newFixedThreadPool蛔添,當然就是nThreads痰催,以為其要求是固定大小,而newCachedThreadPool則是Integer.VALUE迎瞧。

3陨囊、keepAliveTime和TimeUnit,這兩個參數(shù)指定了額外的線程能夠閑置多久夹攒,顯然有些線程池不需要它蜘醋。

4、workQueue咏尝,工作隊列压语,必須是BlockingQueue。

通過配置不同的參數(shù)编检,我們就可以創(chuàng)建出行為大相徑庭的線程池胎食,這就是線程池高度靈活性的基礎(chǔ)。

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

RejectedExecutionHandler handler) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), handler);

}


newCachedThreadPool

創(chuàng)建一個可緩存線程池允懂,如果線程池長度超過處理需要厕怜,可靈活回收空閑線程,若無可回收蕾总,則新建線程粥航。示例代碼如下:


newCachedThreadPool

線程池為無限大,當執(zhí)行第二個任務(wù)時第一個任務(wù)已經(jīng)完成生百,會復(fù)用執(zhí)行第一個任務(wù)的線程递雀,而不用每次新建線程。



newFixedThreadPool

創(chuàng)建一個定長線程池蚀浆,可控制線程最大并發(fā)數(shù)缀程,超出的線程會在隊列中等待。示例代碼如下:


newFixedThreadPool

因為線程池大小為3市俊,每個任務(wù)輸出index后sleep 2秒杨凑,所以每兩秒打印3個數(shù)字。

定長線程池的大小最好根據(jù)系統(tǒng)資源進行設(shè)置摆昧。如Runtime.getRuntime().availableProcessors()



newScheduledThreadPool

創(chuàng)建一個定長線程池撩满,支持定時及周期性任務(wù)執(zhí)行。延遲執(zhí)行示例代碼如下:


延遲3秒執(zhí)行


延遲1秒后每3秒執(zhí)行一次




newSingleThreadExecutor

創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù)鹦牛,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行搞糕。示例代碼如下:


順序執(zhí)行各個任務(wù)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市曼追,隨后出現(xiàn)的幾起案子窍仰,更是在濱河造成了極大的恐慌,老刑警劉巖礼殊,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驹吮,死亡現(xiàn)場離奇詭異,居然都是意外死亡晶伦,警方通過查閱死者的電腦和手機碟狞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婚陪,“玉大人族沃,你說我怎么就攤上這事∶诓危” “怎么了脆淹?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長沽一。 經(jīng)常有香客問我盖溺,道長,這世上最難降的妖魔是什么铣缠? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任烘嘱,我火速辦了婚禮,結(jié)果婚禮上蝗蛙,老公的妹妹穿的比我還像新娘蝇庭。我一直安慰自己,他們只是感情好歼郭,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布遗契。 她就那樣靜靜地躺著,像睡著了一般病曾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漾根,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天泰涂,我揣著相機與錄音,去河邊找鬼辐怕。 笑死逼蒙,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的寄疏。 我是一名探鬼主播是牢,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼僵井,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驳棱?” 一聲冷哼從身側(cè)響起批什,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎社搅,沒想到半個月后驻债,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡形葬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年合呐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笙以。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡淌实,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猖腕,到底是詐尸還是另有隱情翩伪,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布谈息,位于F島的核電站缘屹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏侠仇。R本人自食惡果不足惜轻姿,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望逻炊。 院中可真熱鬧互亮,春花似錦、人聲如沸余素。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桨吊。三九已至威根,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間视乐,已是汗流浹背洛搀。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佑淀,地道東北人留美。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親谎砾。 傳聞我的和親對象是個殘疾皇子逢倍,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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