執行緒池建立方式

欢乐豆123發表於2024-11-09

執行緒池建立方式

一、方式一:透過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

相關文章