執行緒池建立方式
一、方式一:透過ThreadPoolExecutor建構函式來建立(推薦)
方式二:透過 Executor 框架的工具類 Executors 來建立。
Executors工具類提供的建立執行緒池的方法如下圖所示:
可以看出,透過Executors工具類可以建立多種型別的執行緒池,包括:
1. FixedThreadPool:固定執行緒數量的執行緒池。該執行緒池中的執行緒數量始終不變。當有一個新的任務提交時,執行緒池中若有空閒執行緒,則立即執行。若沒有,則新的任務會被暫存在一個任務佇列中,待有執行緒空閒時,便處理在任務佇列中的任務。
2. SingleThreadExecutor
只有一個執行緒的執行緒池。若多餘一個任務被提交到該執行緒池,任務會被儲存在一個任務佇列中,待執行緒空閒,按先入先出的順序執行佇列中的任務。
3. CachedThreadPool: 可根據實際情況調整執行緒數量的執行緒池。執行緒池的執行緒數量不確定,但若有空閒執行緒可以複用,則會優先使用可複用的執行緒。若所有執行緒均在工作,又有新的任務提交,則會建立新的執行緒處理任務。所有執行緒在當前任務執行完畢後,將返回執行緒池進行復用。
4. ScheduledThreadPool
給定的延遲後執行任務或者定期執行任務的執行緒池。
《阿里巴巴 Java 開發手冊》強制執行緒池不允許使用 Executors 去建立,而是透過 ThreadPoolExecutor 建構函式的方式,這樣的處理方式讓開發同學更加明確執行緒池的執行規則,規避資源耗盡的風險。
Executors 返回執行緒池物件的弊端如下(後文會詳細介紹到):
1. FixedThreadPool 和 SingleThreadExecutor
使用的是無界的 LinkedBlockingQueue,任務佇列最大長度為 Integer.MAX_VALUE,可能堆積大量的請求,從而導致 OOM。
部分原始碼如下:
// 無界佇列 LinkedBlockingQueue public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()); } // 無界佇列 LinkedBlockingQueue public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>())); }
2. CachedThreadPool
使用的是同步佇列SynchronousQueue, 允許建立的執行緒數量為 Integer.MAX_VALUE ,如果任務數量過多且執行速度較慢,可能會建立大量的執行緒,從而導致 OOM。
// 同步佇列 SynchronousQueue,沒有容量,最大執行緒數是 Integer.MAX_VALUE` public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>()); }
3. ScheduledThreadPool 和 SingleThreadScheduledExecutor
使用的無界的延遲阻塞佇列 DelayedWorkQueue,任務佇列最大長度為 Integer.MAX_VALUE,可能堆積大量的請求,從而導致 OOM。
// DelayedWorkQueue(延遲阻塞佇列) public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }
參考連結:
https://javaguide.cn/java/concurrent/java-thread-pool-summary.html