Java并發(fā)線程之線程池的知識(shí)總結(jié)
初始化線程池后,把任務(wù)丟進(jìn)去,等待調(diào)度就可以了,使用起來比較方便。
JAVA中Thread是線程類,不建議直接使用Thread執(zhí)行任務(wù),在并發(fā)數(shù)量比較多的情況下,每個(gè)線程都是執(zhí)行一個(gè)很短的時(shí)間就任務(wù)結(jié)束了,這樣頻繁創(chuàng)建線程會(huì)大大降低系統(tǒng)的效率,因?yàn)轭l繁的創(chuàng)建和銷毀線程需要時(shí)間。而線程池可以復(fù)用,就是執(zhí)行完一個(gè)任務(wù),并不銷毀,而是可以繼續(xù)執(zhí)行其它任務(wù)。
Thread的弊端
- 每次
new Thread()創(chuàng)建對(duì)象,性能差。 - 線程缺乏統(tǒng)一管理,可能無限制創(chuàng)建線程,相互競爭,有可能占用過多系統(tǒng)資源導(dǎo)致死機(jī)或OOM。
- 不能多執(zhí)行,定期執(zhí)行,線程中斷
線程池的優(yōu)點(diǎn)
- 重用存在的線程,減少對(duì)象創(chuàng)建,消亡的開銷,性能佳,降低資源消耗。
- 可以控制最大并發(fā)線程數(shù),提高系統(tǒng)資源利用率,同時(shí)避免過多資源競爭,避免阻塞,提高響應(yīng)速度。
- 提供定時(shí)執(zhí)行,定期執(zhí)行,單線程,并發(fā)數(shù)控制等功能,以提高線程的可管理性。
阿里發(fā)布的 Java 開發(fā)手冊(cè)中強(qiáng)制線程池不允許使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。
Executors利用工廠模式向我們提供了4種線程池實(shí)現(xiàn)方式,但是并不推薦使用,原因是使用Executors創(chuàng)建線程池不會(huì)傳入相關(guān)參數(shù)而使用默認(rèn)值所以我們常常忽略了那些重要的參數(shù)(線程池大小、緩沖隊(duì)列的類型等),而且默認(rèn)使用的參數(shù)會(huì)導(dǎo)致資源浪費(fèi),不可取。
ThreadPoolExecutor介紹
構(gòu)造函數(shù)和參數(shù)

java.uitl.concurrent.ThreadPoolExecutor類是線程池中最核心的一個(gè)類。
public class ThreadPoolExecutor extends AbstractExecutorService {
/** 構(gòu)造函數(shù) 1 */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {}
/** 構(gòu)造函數(shù) 2 */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {}
/** 構(gòu)造函數(shù) 3 */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {}
/** 構(gòu)造函數(shù) 4 */
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}
}
ThreadPoolExecutor類中提供了四個(gè)構(gòu)造方法,在構(gòu)造函數(shù)4中,參數(shù)最多,通過觀察其他3個(gè)構(gòu)造函數(shù),發(fā)現(xiàn)前面三個(gè)構(gòu)造器都是調(diào)用的第四個(gè)構(gòu)造器進(jìn)行的初始化工作。

構(gòu)造器中各個(gè)參數(shù)的含義
corePoolSize 核心線程池的大小,在創(chuàng)建了線程池后,默認(rèn)情況下,線程池中沒有任何的線程池,而是等任務(wù)過來了再去創(chuàng)建線程執(zhí)行任務(wù)。除非調(diào)用了預(yù)創(chuàng)建線程的方法,即在沒有任務(wù)到來之前就創(chuàng)建corePoolSize個(gè)線程或者一個(gè)線程。當(dāng)線程池中的線程數(shù)量到達(dá)corePoolSize后,就會(huì)把到達(dá)的任務(wù)放到緩存隊(duì)列里面。
- prestartCoreThread() : 預(yù)創(chuàng)建一個(gè)核心線程,使其閑置等待工作。
- prestartAllCoreThreads() : 啟動(dòng)所有核心線程,導(dǎo)致它們空閑地等待工作。
maxnumPoolSize 線程池中最大的線程數(shù),是一個(gè)非常重要的參數(shù),它表示在線程池中最多能創(chuàng)建多少線程。
keepAliveTime 表示線程在沒有任務(wù)執(zhí)行時(shí)最多保持多久時(shí)間會(huì)終止。默認(rèn)情況下,只有當(dāng)線程池中的線程數(shù)大于corePoolSize時(shí),keepAliveTime才會(huì)起作用,即當(dāng)線程池中的線程數(shù)大于corePoolSize,如果一個(gè)線程的空閑時(shí)間達(dá)到keepAliveTime,則會(huì)終止直到線程池中的線程數(shù)量不大于corePoolSize。但是如果調(diào)用了allowCoreThreadTimeOut(boolean)方法,在線程池中線程數(shù)不大于corePoolSize時(shí),keepAliveTime參數(shù)也會(huì)啟作用,直到線程池中的線程數(shù)為0。unit 參數(shù)
keepAliveTime的時(shí)間單位,有7種取值,在TimeUnit類中有7種靜態(tài)屬性。
- TimeUnit.DAYS : 以 天 為單位 ;
- TimeUnit.HOURS : 以 小時(shí) 為單位 ;
- TimeUnit.MINUTES : 以 分鐘 為單位 ;
- TimeUnit.SECONDS : 以 秒 為單位 ;
- TimeUnit.MILLISECONDS : 以 毫秒 為單位 ;
- TimeUnit.MICROSECONDS : 以 微秒 為單位 ;
- TimeUnit.NANOSECONDS : 以 納秒 為單位 ;
workQueue一個(gè)阻塞隊(duì)列,用來存儲(chǔ)等待執(zhí)行的任務(wù),這個(gè)參數(shù)的選擇也很重要,會(huì)對(duì)線程池的運(yùn)行過程產(chǎn)生重大影響,一般有以下幾種選擇。
- ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列,創(chuàng)建時(shí)必須指定大小。
- LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列,若果創(chuàng)建時(shí)沒有指定此隊(duì)列的大小,則默認(rèn)為
Integer.MAX_VALUE。 - SynchronousQueue:這個(gè)隊(duì)列比較特殊,它不會(huì)保存提交的任務(wù),而是直接新建一個(gè)線程來執(zhí)行新的任務(wù)。
threadFactory線程工廠,主要用來創(chuàng)建線程。線程池最重要的一項(xiàng)工作,就是在滿足某些條件情況下創(chuàng)建線程。在
ThreadPoolExecutor線程池中,創(chuàng)建線程的操作時(shí)交給ThreadFactoty來完成。使用線程池,就必須要指定threadFactory。如果我們的構(gòu)造器中沒有指定使用ThreadFactory,這個(gè)時(shí)候ThreadPoolExecutor就會(huì)使用默認(rèn)的ThreadFactory:DefaultThreadFactoryhandler 在ThreadPoolExecutor線程池中還有一個(gè)重要的接口:RejectedExecutionHandler。當(dāng)提交給線程池的某一個(gè)新任務(wù)無法直接被線程池中“核心線程”直接處理,又無法加入等待隊(duì)列,也無法創(chuàng)建新的線程執(zhí)行;又或者線程池已經(jīng)調(diào)用shutdown()方法停止了工作;又或者線程池不是處于正常的工作狀態(tài);這時(shí)候ThreadPoolExecutor線程池會(huì)拒絕處理這個(gè)任務(wù),觸發(fā)創(chuàng)建ThreadPoolExecutor線程池時(shí)定義的RejectedExecutionHandler接口的實(shí)現(xiàn),表示當(dāng)拒絕處理任務(wù)時(shí)的策略,有以下四種取值,四種值都為其靜態(tài)內(nèi)部類:
- ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常
- ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
- ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行新提交的任務(wù)。
ThreadPoolExecutor執(zhí)行execute方法分下面4種情況
- 如果當(dāng)前運(yùn)行的線程少于
corePoolSize,則創(chuàng)建新的線程來執(zhí)行任務(wù)(執(zhí)行這一步驟需要獲取全局鎖) - 如果運(yùn)行的線程等于或者多于
corePoolSize,則將任務(wù)加入到BlockingQueue - 如果無法將任務(wù)加入
BlockingQueue(隊(duì)列已滿),則創(chuàng)建新的線程來處理任務(wù)(執(zhí)行這一步驟需要獲取全局鎖) - 如果創(chuàng)建新線程將當(dāng)前運(yùn)行的線程超出
maxnumPoolSize,任務(wù)被拒絕,并調(diào)用RejectedExecutionHandler.rejectedExecution()方法。
以上就是Java并發(fā)線程之線程池的知識(shí)總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java 線程池的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MybatisPlus查詢條件為空字符串或null問題及解決
這篇文章主要介紹了MybatisPlus查詢條件為空字符串或null問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
解決mybatis-plus-boot-starter與mybatis-spring-boot-starter的錯(cuò)誤問題
本文主要講述了在使用MyBatis和MyBatis-Plus時(shí)遇到的綁定異常問題,通過排查和總結(jié),作者發(fā)現(xiàn)使用MyBatis-Plus?Boot?Starter可以解決這個(gè)問題,文章詳細(xì)對(duì)比了MyBatis-Plus?Boot?Starter和MyBatis?Spring?Boot?Starter的功能和使用場景2025-01-01
java程序設(shè)計(jì)語言的優(yōu)勢及特點(diǎn)
在本篇文章里小編給大家分享的是一篇關(guān)于java程序設(shè)計(jì)語言的優(yōu)勢及特點(diǎn)的內(nèi)容,需要的朋友們可以學(xué)習(xí)參考下。2020-02-02
Java中弱引用和軟引用的區(qū)別以及虛引用和強(qiáng)引用介紹
很早Java API就添加了弱引用(WeakReference)和軟引用(SoftReference),但并不是所有的程序員都熟悉這兩個(gè)概念2014-04-04
通過實(shí)例學(xué)習(xí)Spring @Required注釋原理
這篇文章主要介紹了通過實(shí)例學(xué)習(xí)Spring @Required注釋原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03
詳解Spring-boot中讀取config配置文件的兩種方式
這篇文章主要介紹了詳解Spring-boot中讀取config配置文件的兩種方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
利用java實(shí)現(xiàn)一個(gè)客戶信息管理系統(tǒng)
這篇文章主要給大家介紹了關(guān)于利用java實(shí)現(xiàn)一個(gè)客戶信息管理系統(tǒng)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

