Java線程池排隊策略 & 拒絕策略

1韧拒、為什么JDK1.5引入線程池

在Java中伞租,如果每個任務(wù)都創(chuàng)建一個新的thread贞谓,開銷是非常大的。除了創(chuàng)建和銷毀線程的時間開銷外葵诈,還消耗大量的系統(tǒng)資源裸弦。為了規(guī)避以上問題,盡可能減少創(chuàng)建和銷毀線程的次數(shù)作喘,特別是一些資源耗費比較大的線程的創(chuàng)建和銷毀理疙,盡量利用已有的線程對象來進(jìn)行服務(wù),這就是線程池引入的原因泞坦。?

2窖贤、ThreadPoolExecutor類分析

(a)ThreadPoolExecutor構(gòu)造函數(shù):



public ThreadPoolExecutor(int corePoolSize,

? int maximumPoolSize,

? long keepAliveTime,

? TimeUnit unit,

? BlockingQueue<Runnable> workQueue,

? ThreadFactory threadFactory,

? RejectedExecutionHandler handler);


1)corePoolSize 核心線程數(shù)?

(2)maximumPoolSize 最大線程數(shù)

(3)keepAliveTime 線程被回收前的空閑時間

(4)workQueue 任務(wù)隊列

(5)threadFactory 線程創(chuàng)建工廠

(6)handler 線程池對拒絕任務(wù)的處理策略

(b)ThreadPoolExecutor運行原理:

ThreadPoolExecutor將根據(jù)corePoolSize和maximumPoolSize設(shè)置的值調(diào)整線程池大小。當(dāng)新任務(wù)調(diào)用方法execute(Runnable)提交時,如果運行的線程少于corePoolSize赃梧,則創(chuàng)建新線程來處理請求滤蝠。如果正在運行的線程數(shù)等于corePoolSize時,則新任務(wù)被添加到隊列中授嘀,直到隊列滿物咳。當(dāng)隊列滿了后,會繼續(xù)開辟新線程來處理任務(wù)蹄皱,但不超過最大線程數(shù)览闰。當(dāng)任務(wù)隊列滿了并且已開辟了最大線程數(shù),此時又來了新任務(wù)巷折,ThreadPoolExecutor會拒絕服務(wù)压鉴。

(c)keepAliveTime注意事項:



/**

* Timeout in nanoseconds for idle threads waiting for work.

* Threads use this timeout when there are more than corePoolSize

* present or if allowCoreThreadTimeOut. Otherwise they wait

* forever for new work.

*/

private volatile long keepAliveTime;



說明:當(dāng)線程空閑超過keepAliveTime,非核心線程會被回收盔几,若allowCoreThreadTimeOut為true則核心線程也會被回收晴弃。



/**

* If false (default), core threads stay alive even when idle.

* If true, core threads use keepAliveTime to time out waiting

* for work.

*/

private volatile boolean allowCoreThreadTimeOut;



說明:默認(rèn)情況下,核心線程不會被回收逊拍;當(dāng)allowCoreThreadTimeOut為true上鞠,核心線程也會被回收。

3芯丧、任務(wù)隊列

BlockingQueue<Runnable> workQueue;

workQueue是一個BlockingQueue接口的對象芍阎,僅用于存放Runnable對象。

(1)直接提交(如SynchronousQueue)

直接提交策略表示線程池不對任務(wù)進(jìn)行緩存缨恒。新進(jìn)任務(wù)直接提交給線程池谴咸,當(dāng)線程池中沒有空閑線程時,創(chuàng)建一個新的線程處理此任務(wù)骗露。這種策略需要線程池具有無限增長的可能性岭佳。

Executors.newCachedThreadPool()使用SynchronousQueue創(chuàng)建線程池。

(2)無界隊列(如不具有預(yù)定義容量的LinkedBlockingQueue)

LinkedBlockingQueue將導(dǎo)致當(dāng)所有 corePoolSize 線程都忙時新任務(wù)在隊列中等待萧锉。這樣珊随,創(chuàng)建的線程就不會超過 corePoolSize。(因此柿隙,maximumPoolSize 的值也就無效了叶洞。)當(dāng)每個任務(wù)完全獨立于其他任務(wù),即任務(wù)執(zhí)行互不影響時禀崖,適合于使用無界隊列衩辟。

Executors.newFixedThreadPool(3)使用LinkedBlockingQueue創(chuàng)建線程池。

Executors.newSingleThreadExecutor()使用LinkedBlockingQueue創(chuàng)建線程池波附。

(3)有界隊列(如ArrayBlockingQueue)

有界隊列(如ArrayBlockingQueue)有助于防止資源耗盡當(dāng)最大線程數(shù)有限時艺晴,但是可能較難調(diào)整和控制昼钻。隊列大小和最大池大小可能需要相互折衷。

(4)優(yōu)先級隊列(如PriorityBlockingQueue)

(5)DelayedWorkQueue

DelayedWorkQueue是ScheduledThreadPoolExecutor的靜態(tài)內(nèi)部類财饥。

Executors.newScheduledThreadPool(3)使用DelayedWorkQueue創(chuàng)建線程池换吧。

4、拒絕策略

接口RejectedExecutionHandler提供了拒絕任務(wù)處理的自定義方法的機(jī)會钥星。在ThreadPoolExecutor中已經(jīng)包含四種拒絕策略沾瓦。

(1)AbortPolicy

拒絕策略:拋出運行時異常RejectedExecutionException。

這種策略丟棄任務(wù)谦炒,并拋出異常贯莺。(jdk默認(rèn)策略)

(2)DiscardPolicy

拒絕策略:不能執(zhí)行的任務(wù)將被丟棄。

這種策略什么都沒做宁改。

(3)DiscardOldestPolicy

拒絕策略:如果執(zhí)行程序尚未關(guān)閉缕探,則位于工作隊列頭部的任務(wù)將被刪除,然后重試執(zhí)行程序还蹲。



public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

? ? if (!e.isShutdown()) {

? ? ? ? e.getQueue().poll();

? ? ? ? e.execute(r);

? ? }

}



該策略稍微復(fù)雜一些爹耗,在pool沒有關(guān)閉的前提下首先丟掉緩存在隊列中的最早的任務(wù),然后重新嘗試運行該任務(wù)谜喊。

(4)CallerRunsPolicy

拒絕策略:線程調(diào)用運行該任務(wù)的 execute 本身潭兽。此策略提供簡單的反饋控制機(jī)制,能夠減緩新任務(wù)的提交速度斗遏。



public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

? ? if (!e.isShutdown()) {

? ? ? ? r.run();

? ? }

}


這個策略不想放棄執(zhí)行任務(wù)山卦。但是由于池中已經(jīng)沒有任何資源了,那么就直接使用調(diào)用該execute的線程本身來執(zhí)行诵次。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末账蓉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子逾一,更是在濱河造成了極大的恐慌铸本,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遵堵,死亡現(xiàn)場離奇詭異箱玷,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鄙早,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門汪茧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來椅亚,“玉大人限番,你說我怎么就攤上這事⊙教颍” “怎么了弥虐?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵扩灯,是天一觀的道長。 經(jīng)常有香客問我霜瘪,道長珠插,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任颖对,我火速辦了婚禮捻撑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缤底。我一直安慰自己顾患,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布个唧。 她就那樣靜靜地躺著江解,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徙歼。 梳的紋絲不亂的頭發(fā)上犁河,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機(jī)與錄音魄梯,去河邊找鬼桨螺。 笑死,一個胖子當(dāng)著我的面吹牛画恰,可吹牛的內(nèi)容都是我干的彭谁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼允扇,長吁一口氣:“原來是場噩夢啊……” “哼缠局!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起考润,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤狭园,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糊治,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唱矛,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年井辜,在試婚紗的時候發(fā)現(xiàn)自己被綠了绎谦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡粥脚,死狀恐怖窃肠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刷允,我是刑警寧澤冤留,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布碧囊,位于F島的核電站,受9級特大地震影響纤怒,放射性物質(zhì)發(fā)生泄漏糯而。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一泊窘、第九天 我趴在偏房一處隱蔽的房頂上張望熄驼。 院中可真熱鬧,春花似錦烘豹、人聲如沸谜洽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阐虚。三九已至,卻和暖如春蚌卤,著一層夾襖步出監(jiān)牢的瞬間实束,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工逊彭, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留咸灿,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓侮叮,卻偏偏與公主長得像避矢,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子囊榜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

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

  • 一.Java中的ThreadPoolExecutor類 java.uitl.concurrent.ThreadPo...
    誰在烽煙彼岸閱讀 645評論 0 0
  • 第一部分 來看一下線程池的框架圖卸勺,如下: 1砂沛、Executor任務(wù)提交接口與Executors工具類 Execut...
    壓抑的內(nèi)心閱讀 4,261評論 1 24
  • 我發(fā)表在簡書上的文章,閱讀量402曙求。 換了個題目碍庵,在公眾號上的閱讀量17817。哎呀悟狱,哎呀静浴,哎呀呀呀,這做人的差距...
    春秋半步閱讀 641評論 9 3
  • 愛情挤渐,顧名思義苹享,因愛產(chǎn)生的感情。古往今來挣菲,多少詩詞圍繞著愛情產(chǎn)生富稻。凄美哀怨的,此情無計可消除白胀,才下眉頭椭赋,卻上...
    我這半輩子閱讀 343評論 5 1
  • 生活總是這樣不能如意,也許老天給你關(guān)上一扇窗的時候就會給你打開一扇門或杠,五年哪怔,不長但在自己看來卻也是不短的...
    A貝貝家微店閱讀 279評論 0 2