重要--深入詳解Java線程池——ThreadPoolExecutor
https://my.oschina.net/ProgramerLife/blog/1811255
重要--Executor框架詳解(Executor框架結構與框架成員)
https://blog.csdn.net/tongdanping/article/details/79604637
重要--java併發編程:Executor、Executors、ExecutorService
https://blog.csdn.net/weixin_40304387/article/details/80508236
重要--面試系列-線程池詳解
https://yq.aliyun.com/articles/655502?spm=a2c4e.11153940.0.0.f4856693bFeAVk
重要--深入詳解Java線程池——ThreadPoolExecutor 詳細解釋了各參數的意義
https://yq.aliyun.com/articles/633780?spm=a2c4e.11153940.0.0.f4856693bFeAVk
重要--合理配置線程池
https://www.cnblogs.com/toov5/p/9836217.html
重要--Java 8系列之重新認識HashMap
https://cloud.tencent.com/developer/article/1343130
雲棲社區-深入詳解Java線程池——Executor框架
https://yq.aliyun.com/articles/633782?utm_content=m_1000015330
Java--死鎖以及死鎖的排查
https://cloud.tencent.com/developer/article/1347601
使用Executors類創建線程池的弊端以及與使用ThreadPoolExecutor類的區別
https://blog.csdn.net/SmallCarrot/article/details/85013098
線程池 -- ThreadPoolExecutor
線程池,其實就是一個容納多個線程的容器,其中的線程可以反覆使用,省去了頻繁創建線程對象的操作,無需反覆創建線程而消耗過多資源。需要的時候從池中獲取線程不用自行創建,使用完畢不需要銷燬線程而是放回池中,從而減少創建和銷燬線程對象的開銷。
ThreadPoolExecutor是Executor接口的一個重要的實現類,是線程池的具體實現,用來執行被提交的任務。
工作者線程的任務很簡單:從工作隊列中獲取一個任務並執行任務,然後返回線程池等待下一個任務。線程池啓動初期線程不會啓動,有任務提交(調用execute或submit)纔會啓動,直到到達最大數量就不再創建而是進入阻塞隊列。
ThreadPoolExecutor定義了很多構造函數,以其中一個爲例:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1、corePoolSize:必需參數,線程池中所保存的核心線程數,包括空閒線程。在創建了線程池之後,默認情況下線程池中沒有任何線程。當提交一個任務到線程池時,線程池會創建一個線程來執行任務,即使其他空閒的基本線程能夠執行新任務也會創建線程,等到需要執行的任務數大於線程池核心線程數時就不再創建。
2、maximumPoolSize:必需參數,線程池中允許的最大線程數,這個參數表示了線程池中最多能創建的線程數量,當任務數量比corePoolSize大時,任務添加到workQueue,當workQueue滿了,將繼續創建線程以處理任務,maximumPoolSize表示的就是wordQueue滿了,線程池中最多可以創建的線程數量。
3、keepAliveTime:必需參數,線程池中的空閒線程所能持續的最長時間。當線程池中的線程數大於corePoolSize時,keepAliveTime爲多餘的空閒線程等待新任務的最長時間,超過這個時間後多餘的線程將被終止。
4、unit:必需參數, keepAliveTime持續時間單位。天、小時、分鐘、秒、毫秒、微秒、納秒。
5、workQueue:必需參數,任務執行前保存等待執行的任務的隊列。
6、threadFactory:非必需參數,不設置此參數會採用內置默認參數(defaultThreadFactory()方法創建屬於同一個ThreadGroup對象的基本線程對象)。也可以自己定義線程工廠,重新實現ThreadFactory中newThread (Runnable)方法,設置屬性等.
7、handler:非必需參數,不設置此參數會採用內置默認參數,設置飽和策略,當隊列和線程池都滿了,說明線程池處於飽和狀態,那麼必須採取一種策略處理提交的新任務。
RejectedExecutionHandler 的實現類在ThreadPoolExecutor中有四個靜態內部類,這個策略默認情況下是AbortPolicy,表示無法處理新任務時拋出異常。共有4中策略:包括AbortPolicy(丟棄任務並拋出RejectedExecutionException異常)、 DiscardPolicy(丟棄任務,但是不拋出異常) 、DiscardOldestPolicy(丟棄執行隊列中最老的任務,嘗試爲當前提交的任務騰出位置)、 CallerRunsPolicy(由調用者所在線程來運行任務)。也可以根據應用場景需要來實現RejectedExecutionHandler接口自定義策略。
當試圖將一個任務添加到線程池中時,按照如下順序來處理:
1、如果線程池中的線程數量少於corePoolSize,即使線程池中有空閒線程,也會創建一個新的線程來執行新添加的任務;
2、如果線程池中的線程數量大於等於corePoolSize,但緩衝隊列workQueue未滿,則將新添加的任務放到workQueue中,按照FIFO的原則依次等待執行(線程池中有線程空閒出來後依次將緩衝隊列中的任務交付給空閒的線程執行);
3、如果線程池中的線程數量大於等於corePoolSize,且緩衝隊列workQueue已滿,但線程池中的線程數量小於maximumPoolSize,則會創建新的線程來處理被添加的任務;
4、如果線程池中的線程數量等於了maximumPoolSize,有4種處理方式。
總結起來,也即是說:
當有新的任務要處理時,先看線程池中的線程數量是否大於corePoolSize,再看緩衝隊列workQueue是否滿,最後看線程池中的線程數量是否大於maximumPoolSize。
另外,當線程池中的線程數量大於corePoolSize時,如果裏面有線程的空閒時間超過了keepAliveTime,就將其移除線程池,這樣,可以動態地調整線程池中線程的數量。