Java線程池ThreadPoolExecutor&&Executors
一、先看看傳統的開啟線程。
new Thread(new Runnable() { @Override public void run() { } }).start();
缺點:
1、每次new Thread新建對象性能差。
2、線程缺乏統一管理,可能無限制新建線程,相互之間競爭,及可能占用過多系統資源導致死機或oom。
3、缺乏更多功能,如定時執行、定期執行、線程中斷。
二、在看看ThreadPoolExecutor。
構造函數:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {}
參數說明:
corePoolSize:線程池核心線程數(平時保留的線程數)
maximumPoolSize:線程池最大線程數(當workQueue都放不下時,啟動新線程,最大線程數)
unit:keepAliveTime單位
workQueue:阻塞隊列,存放來不及執行的線程
ArrayBlockingQueue:構造函數一定要傳大小
LinkedBlockingQueue:構造函數不傳大小會默認為(Integer.MAX_VALUE ),當大量請求任務時,容易造成 內存耗盡。
SynchronousQueue:同步隊列,一個沒有存儲空間的阻塞隊列 ,將任務同步交付給工作線程。
PriorityBlockingQueue : 優先隊列
threadFactory:線程工廠
handler:飽和策略
CallerRunsPolicy:用調用者的線程執行任務
DiscardOldestPolicy:拋棄隊列中最久的任務
DiscardPolicy:拋棄當前任務
劃重點:
1、當線程池小於corePoolSize時,新提交任務將創建一個新線程執行任務,即使此時線程池中存在空閑線程。
2、當線程池達到corePoolSize時,新提交任務將被放入workQueue中,等待線程池中任務調度執行
3、當workQueue已滿,且maximumPoolSize>corePoolSize時,新提交任務會創建新線程執行任務
4、當提交任務數超過maximumPoolSize時,新提交任務由RejectedExecutionHandler處理
5、當線程池中超過corePoolSize線程,空閑時間達到keepAliveTime時,關閉空閑線程
6、當設置allowCoreThreadTimeOut(true)時,線程池中corePoolSize線程空閑時間達到keepAliveTime也將關閉
三、Executors可創建預定義的線程池
1、FixedThreadPool:創建一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
特點:
1)、corePoolSize與maximumPoolSize相等,即其線程全為核心線程,是一個固定大小的線程池,是其優勢;
2)、keepAliveTime = 0 該參數默認對核心線程無效,而FixedThreadPool全部為核心線程;
3)、workQueue 為LinkedBlockingQueue(無界阻塞隊列),隊列最大值為Integer.MAX_VALUE。如果任務提交速度持續大余任務處理速度,會造成隊列大量阻塞。因為隊列很大,很有可能在拒絕策略前,內存溢出。是其劣勢;
4)、FixedThreadPool的任務執行是無序的;
適用場景:可用於Web服務瞬時削峰,但需註意長時間持續高峰情況造成的隊列阻塞。
2、CachedThreadPool:創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
特點:
1)、corePoolSize = 0,maximumPoolSize = Integer.MAX_VALUE,即線程數量幾乎無限制;
2)、keepAliveTime = 60s,線程空閑60s後自動結束。
3)、workQueue 為 SynchronousQueue 同步隊列,這個隊列類似於一個接力棒,入隊出隊必須同時傳遞,因為CachedThreadPool線程創建無限制,不會有隊列等待,所以使用SynchronousQueue;
適用場景:快速處理大量耗時較短的任務,如Netty的NIO接受請求時,可使用CachedThreadPool。
3、SingleThreadExecutor:創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
4、ScheduledThreadPool:創建一個定長線程池,支持定時及周期性任務執行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); }
代碼樣例:
public class Test { private ExecutorService cachePool = Executors.newCachedThreadPool(); private void test() { for (int i = 0; i < 10; i++) { cachePool.execute(new Job()); } cachePool.shutdown(); } class Job implements Runnable { @Override public void run() { System.out.println("執行任務"); try { Thread.sleep(3000); } catch (InterruptedException e) { } } } public static void main(String[] args) { new ExecutorServiceTest().test(); } }
參考:
https://www.jianshu.com/p/f030aa5d7a28
https://segmentfault.com/a/1190000015368896?utm_source=tag-newest
Java線程池ThreadPoolExecutor&&Executors