溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

最詳細(xì)的Java線程池原理解析

發(fā)布時(shí)間:2020-06-21 15:49:58 來(lái)源:網(wǎng)絡(luò) 閱讀:6299 作者:Java_老男孩 欄目:編程語(yǔ)言

一、為什么要用線程池

  1. 降低資源消耗。通過(guò)重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建、銷毀線程造成的消耗。

  2. 提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時(shí),任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行。

  3. 提高線程的可管理性。線程是稀缺資源,如果無(wú)限制的創(chuàng)建,不僅會(huì)消耗系統(tǒng)資源,還會(huì)降低系統(tǒng)的穩(wěn)定性,使用線程池可以進(jìn)行統(tǒng)一的分配、調(diào)優(yōu)和監(jiān)控

二、ThreadPoolExecutor線程池類參數(shù)詳解

參數(shù) 說(shuō)明
corePoolSize 核心線程數(shù)量,線程池維護(hù)線程的最少數(shù)量
maximumPoolSize 線程池維護(hù)線程的最大數(shù)量
keepAliveTime 線程池除核心線程外的其他線程的最長(zhǎng)空閑時(shí)間,超過(guò)該時(shí)間的空閑線程會(huì)被銷毀
unit keepAliveTime的單位,TimeUnit中的幾個(gè)靜態(tài)屬性:NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS
workQueue 線程池所使用的任務(wù)緩沖隊(duì)列
threadFactory 線程工廠,用于創(chuàng)建線程,一般用默認(rèn)的即可
handler 線程池對(duì)拒絕任務(wù)的處理策略

當(dāng)線程池任務(wù)處理不過(guò)來(lái)的時(shí)候(什么時(shí)候認(rèn)為處理不過(guò)來(lái)后面描述),可以通過(guò)handler指定的策略進(jìn)行處理,ThreadPoolExecutor提供了四種策略:

  1. ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常;也是默認(rèn)的處理方式。
  2. ThreadPoolExecutor.DiscardPolicy:丟棄任務(wù),但是不拋出異常。
  3. ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過(guò)程)
  4. ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)

可以通過(guò)實(shí)現(xiàn)RejectedExecutionHandler接口自定義處理方式。

三、線程池任務(wù)執(zhí)行

1. 添加執(zhí)行任務(wù)

  • submit() 該方法返回一個(gè)Future對(duì)象,可執(zhí)行帶返回值的線程;或者執(zhí)行想隨時(shí)可以取消的線程。Future對(duì)象的get()方法獲取返回值。Future對(duì)象的cancel(true/false)取消任務(wù),未開(kāi)始或已完成返回false,參數(shù)表示是否中斷執(zhí)行中的線程
  • execute() 沒(méi)有返回值。

2. 線程池任務(wù)提交過(guò)程

2.1. 如果此時(shí)線程池中的數(shù)量小于corePoolSize,即使線程池中的線程都處于空閑狀態(tài),也要?jiǎng)?chuàng)建新的線程來(lái)處理被添加的任務(wù)。
2.2. 如果此時(shí)線程池中的數(shù)量等于corePoolSize,但是緩沖隊(duì)列workQueue未滿,那么任務(wù)被放入緩沖隊(duì)列。
2.3. 如果此時(shí)線程池中的數(shù)量大于等于corePoolSize,緩沖隊(duì)列workQueue滿,并且線程池中的數(shù)量小于maximumPoolSize,建新的線程來(lái)處理被添加的任務(wù)。
2.4. 如果此時(shí)線程池中的數(shù)量大于corePoolSize,緩沖隊(duì)列workQueue滿,并且線程池中的數(shù)量等于maximumPoolSize,那么通過(guò) handler所指定的策略來(lái)處理此任務(wù)。
2.5. 當(dāng)線程池中的線程數(shù)量大于 corePoolSize時(shí),如果某線程空閑時(shí)間超過(guò)keepAliveTime,線程將被終止。這樣,線程池可以動(dòng)態(tài)的調(diào)整池中的線程數(shù)。

總結(jié)即:處理任務(wù)判斷的優(yōu)先級(jí)為 核心線程corePoolSize、任務(wù)隊(duì)列workQueue、最大線程maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務(wù)。

注意:

  1. 當(dāng)workQueue使用的是×××限隊(duì)列時(shí),maximumPoolSize參數(shù)就變的無(wú)意義了,比如new LinkedBlockingQueue(),或者new ArrayBlockingQueue(Integer.MAX_VALUE);
  2. 使用SynchronousQueue隊(duì)列時(shí)由于該隊(duì)列沒(méi)有容量的特性,所以不會(huì)對(duì)任務(wù)進(jìn)行排隊(duì),如果線程池中沒(méi)有空閑線程,會(huì)立即創(chuàng)建一個(gè)新線程來(lái)接收這個(gè)任務(wù)。maximumPoolSize要設(shè)置大一點(diǎn)。
  3. 核心線程和最大線程數(shù)量相等時(shí)keepAliveTime無(wú)作用.

3. 線程池關(guān)閉

3.1. shutdown() 不接收新任務(wù),會(huì)處理已添加任務(wù)
3.2. shutdownNow() 不接受新任務(wù),不處理已添加任務(wù),中斷正在處理的任務(wù)

4. 常用隊(duì)列介紹

4.1. ArrayBlockingQueue: 這是一個(gè)由數(shù)組實(shí)現(xiàn)的容量固定的有界阻塞隊(duì)列.
4.2. SynchronousQueue: 沒(méi)有容量,不能緩存數(shù)據(jù);每個(gè)put必須等待一個(gè)take; offer()的時(shí)候如果沒(méi)有另一個(gè)線程在poll()或者take()的話返回false。
4.3. LinkedBlockingQueue: 這是一個(gè)由單鏈表實(shí)現(xiàn)的默認(rèn)×××的阻塞隊(duì)列。LinkedBlockingQueue提供了一個(gè)可選有界的構(gòu)造函數(shù),而在未指明容量時(shí),容量默認(rèn)為Integer.MAX_VALUE。

隊(duì)列操作:

方法 說(shuō)明
add 增加一個(gè)元索; 如果隊(duì)列已滿,則拋出一個(gè)異常
remove 移除并返回隊(duì)列頭部的元素; 如果隊(duì)列為空,則拋出一個(gè)異常
offer 添加一個(gè)元素并返回true; 如果隊(duì)列已滿,則返回false
poll 移除并返回隊(duì)列頭部的元素; 如果隊(duì)列為空,則返回null
put 添加一個(gè)元素; 如果隊(duì)列滿,則阻塞
take 移除并返回隊(duì)列頭部的元素; 如果隊(duì)列為空,則阻塞
element 返回隊(duì)列頭部的元素; 如果隊(duì)列為空,則拋出一個(gè)異常
peek 返回隊(duì)列頭部的元素; 如果隊(duì)列為空,則返回null

5. Executors線程工廠類

1. Executors.newCachedThreadPool();
說(shuō)明: 創(chuàng)建一個(gè)可緩存線程池,如果線程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線程,若無(wú)可回收,則新建線程.
內(nèi)部實(shí)現(xiàn):new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.SECONDS,new SynchronousQueue<runnable>());</runnable>

2. Executors.newFixedThreadPool(int);
說(shuō)明: 創(chuàng)建一個(gè)定長(zhǎng)線程池,可控制線程最大并發(fā)數(shù),超出的線程會(huì)在隊(duì)列中等待。
內(nèi)部實(shí)現(xiàn):new ThreadPoolExecutor(nThreads, nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>());</runnable>

3. Executors.newSingleThreadExecutor();
說(shuō)明:創(chuàng)建一個(gè)單線程化的線程池,它只會(huì)用唯一的工作線程來(lái)執(zhí)行任務(wù),保證所有任務(wù)按照順序執(zhí)行。
內(nèi)部實(shí)現(xiàn):new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<runnable>())</runnable>

4. Executors.newScheduledThreadPool(int);
說(shuō)明:創(chuàng)建一個(gè)定長(zhǎng)線程池,支持定時(shí)及周期性任務(wù)執(zhí)行。
內(nèi)部實(shí)現(xiàn):new ScheduledThreadPoolExecutor(corePoolSize)

【附】阿里巴巴Java開(kāi)發(fā)手冊(cè)中對(duì)線程池的使用規(guī)范

  1. 【強(qiáng)制】創(chuàng)建線程或線程池時(shí)請(qǐng)指定有意義的線程名稱,方便出錯(cuò)時(shí)回溯。
    正例:

    public class TimerTaskThread extends Thread {
    public TimerTaskThread(){
        super.setName("TimerTaskThread"); 
        ...
    }
    }
  2. 【強(qiáng)制】線程資源必須通過(guò)線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程。
    說(shuō)明: 使用線程池的好處是減少在創(chuàng)建和銷毀線程上所花的時(shí)間以及系統(tǒng)資源的開(kāi)銷,解決資
    源不足的問(wèn)題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類線程而導(dǎo)致消耗完內(nèi)存或者
    “過(guò)度切換”的問(wèn)題。

  3. 【強(qiáng)制】線程池不允許使用 Executors 去創(chuàng)建,而是通過(guò) ThreadPoolExecutor 的方式,這樣
    的處理方式讓寫(xiě)的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。

說(shuō)明: Executors 返回的線程池對(duì)象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:
允許的請(qǐng)求隊(duì)列長(zhǎng)度為 Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致 OOM。
2) CachedThreadPool 和 ScheduledThreadPool:
允許的創(chuàng)建線程數(shù)量為 Integer.MAX_VALUE, 可能會(huì)創(chuàng)建大量的線程,從而導(dǎo)致 OOM。

6. 總結(jié)

ThreadPoolExecutor通過(guò)幾個(gè)核心參數(shù)來(lái)定義不同類型的線程池,適用于不同的使用場(chǎng)景;其中在任務(wù)提交時(shí),會(huì)依次判斷corePoolSize, workQueque, 及maximumPoolSize,不同的狀態(tài)不同的處理。技術(shù)領(lǐng)域水太深,如果不是日常使用,基本一段時(shí)間后某些知識(shí)點(diǎn)就忘的差不多了,因此階段性地回顧與總結(jié),對(duì)夯實(shí)自己的技術(shù)基礎(chǔ)很有必要。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI