Java的線程池ThreadPoolExecutor及多種線程池實現(xiàn)詳解
1、線程池狀態(tài)含義
ThreadPoolExecutor 使用 int 的高 3 位來表示線程池狀態(tài),低 29 位表示線程數(shù)量,之所以將信息存儲在一個變量中,是為了保證原子性。
具體的高三位與線程池狀態(tài)如下,引用自網(wǎng)課的圖片:
2、構(gòu)造方法的參數(shù)、具體工作方式
public ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
對于以上變量,其含義如下:corePoolSize 核心線程數(shù)目 (最多保留的線程數(shù))
- maximumPoolSize 最大線程數(shù)目
- keepAliveTime 生存時間
- unit 生存時間的時間單位
- workQueue 阻塞隊列
- threadFactory 線程工廠 - 可以為線程創(chuàng)建時起個好名字
- handler 拒絕策略
具體解釋:
1.核心線程數(shù):是指在線程池中始終保持存活的線程數(shù)量。在線程池中,當有新的任務(wù)到達時,線程池會創(chuàng)建新的線程來處理任務(wù),但是當任務(wù)處理完畢后,線程并不會立即銷毀,而是被放置在線程池中等待下一個任務(wù)的到來。 當將allowCoreThreadTimeout設(shè)置為 true 時,核心線程也會超時回收,像這樣:
executor.allowCoreThreadTimeOut(true); // 允許回收核心線程
2.最大線程數(shù)目:指核心線程數(shù)+非核心線程數(shù)的總數(shù)。例如設(shè)置核心為5,最大為10,那么非核心(救急)則為10-5=5個
3.生存時間:線程閑置超時時長。如果超過該時長,非核心線程就會被回收。如果將allowCoreThreadTimeout設(shè)置為 true 時,核心線程也會超時回收。
4.阻塞隊列:如果核心線程都被占用沒有空閑,此時又多來了新任務(wù),則新來的任務(wù)會被加入阻塞隊列阻塞等待。
5.拒絕策略:如果阻塞隊列滿了,繼續(xù)來任務(wù),那么就創(chuàng)建救急線程來執(zhí)行新任務(wù),但如果救急線程也不夠(達到最大線程數(shù)),再來任務(wù),因為線程池已經(jīng)填滿了到極限了,所以就要拒絕新來的任務(wù)了。jdk和各種框架有多種拒絕策略的實現(xiàn):
- AbortPolicy 讓調(diào)用者拋出 RejectedExecutionException 異常,這是默認策略
- CallerRunsPolicy 讓調(diào)用者運行任務(wù)
- DiscardPolicy 放棄本次任務(wù)
- DiscardOldestPolicy 放棄隊列中最早的任務(wù),本任務(wù)取而代之
- ActiveMQ 的實現(xiàn),帶超時等待(60s)嘗試放入隊列(較好)
3、線程池有哪些常用的實現(xiàn)方式
3.1 newFixedThreadPool
全是、多個核心線程不回收
fixed,即“固定的”,線程數(shù)固定,能夠控制線程的最大并發(fā)數(shù):
(1)源碼中,其核心線程數(shù)和最大線程數(shù)都是nThreads,即相等,說明沒有非核心線程
(2)阻塞隊列是無界的,可以放任意數(shù)量的任務(wù)。
(3)核心線程不會自動回收,直到被明確打斷:“The threads in the pool will exist until it is explicitly shutdown.”
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
//具體使用示例 //1.創(chuàng)建定長線程池對象,線程數(shù)量固定為3 ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); //2. 創(chuàng)建Runnable線程對象以及執(zhí)行的任務(wù) Runnable task =new Runnable(){ public void run() { System.out.println("執(zhí)行任務(wù)啦"); } }; //3. 向線程池提交任務(wù) fixedThreadPool.execute(task);
3.2newCachedThreadPool
全是非核心,定時回收
Cached,緩存,是說這種線程池的實現(xiàn)像緩存一樣是可變的:
(1)核心線程數(shù)是 0, 最大線程數(shù)是 Integer.MAX_VALUE,線程的空閑生存時間是 60s,意味著:這種線程池內(nèi)都是非核心線程、可以無限創(chuàng)建、定時60s回收。
(2)隊列采用了 SynchronousQueue ,特點是,它沒有容量,沒有線程來取是放不進去的。
(3)適合場景:執(zhí)行大量、耗時少的任務(wù)。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
3.3newSingleThreadExecutor
就一個核心線程,不回收
Single,即單線程的線程池:只有 1 個核心線程,無非核心線程,執(zhí)行后不會立即回收。 這樣相當于順序執(zhí)行,不需要處理線程同步問題。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
3.4newScheduledThreadPool
核心非核心都有,非核心定時回收
Scheduled即定時的:核心線程數(shù)量固定,非核心線程數(shù)量無限多但會定時回收,當非核心線程執(zhí)行完閑置 10ms 后則回收,任務(wù)隊列為延時阻塞隊列。 應(yīng)用場景:執(zhí)行定時或周期性的任務(wù)。
private static final long DEFAULT_KEEPALIVE_MILLIS = 10L;
到此這篇關(guān)于Java的線程池ThreadPoolExecutor及多種線程池實現(xiàn)詳解的文章就介紹到這了,更多相關(guān)Java線程池ThreadPoolExecutor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot項目執(zhí)行腳本 自動拉取最新代碼并重啟的實例內(nèi)容
在本篇文章里小編給大家整理的是一篇關(guān)于SpringBoot項目執(zhí)行腳本 自動拉取最新代碼并重啟的實例內(nèi)容,有需要的朋友們參考下。2019-12-12springboot druid數(shù)據(jù)庫連接池連接失敗后一直重連的解決方法
本文主要介紹了springboot druid數(shù)據(jù)庫連接池連接失敗后一直重連的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-04-04SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表
本文主要介紹了SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫分表,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03maven插件spring-boot-starter-tomcat的使用方式
這篇文章主要介紹了maven插件spring-boot-starter-tomcat的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07Java面試Socket編程常用參數(shù)設(shè)置源碼問題分析
這篇文章主要為大家介紹了Java編程中關(guān)于Socket結(jié)構(gòu)分析,常用參數(shù)設(shè)置源碼示例以及面試中的問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-03-03Java數(shù)據(jù)結(jié)構(gòu)之HashMap和HashSet
這篇文章主要介紹了HashMap和HashSet,什么是哈希表以及HashMap的部分源碼解讀,想了解更多的小伙伴,可以參考閱讀本文2023-03-03