Excutors 與 ThreadPoolExcutor 的關係與區別

knqiufan發表於2024-03-22

先說結論。
執行緒池的建立分為兩種:

  • Executors
  • ThreadPoolExecutor

Executors 是一個執行緒池的工具類,而 ThreadPoolExecutorExecutors 的具體實現。ThreadPoolExecutorExecutor 介面的一個實現,是執行緒池的核心類。Executors 工具類提供了很多方法來建立不同型別的執行緒池,比如 newFixedThreadPool(建立固定執行緒數的執行緒池)、newCachedThreadPool(建立緩衝執行緒池)、newSingleThreadPool(建立只有一個執行緒的執行緒池)等,但內部都是透過構造 ThreadPoolExecutor 的不同引數例項來構造執行緒池的。
所以 Executors 適用於想快速建立一個執行緒池而不在意內部實現的場景,而 ThreadPoolExecutor 更為靈活可控,可自定義建立擁有特定配置的執行緒池。
說完的結論再來詳細說說 ExecutorsThreadPoolExecutor

Executors

Executors 建立執行緒池的方式有以下幾種:

  • Executors.newFixedThreadPool:建立固定大小的執行緒池
  • Executors.newWorkStealingPool:建立搶佔式執行緒池
  • Executors.newSingleThreadExecutor:建立單個執行緒的執行緒池
  • Executors.newCachedThreadPool:建立可快取的執行緒池
  • Executors.newSingleThreadScheduledExecutor:建立單執行緒可執行延遲任務的執行緒池
  • Executros.newScheduledThreadPool:建立可執行延遲任務的執行緒池

可以看下原始碼:

public class Executors {
    /**
     * 建立可重用的固定數量的執行緒池。如果所有執行緒都處在活動狀態,提交額外任務
     * 的時候,超出的執行緒在佇列中等待。佇列型別是 LinkedBlockingQueue
     * nThreads 為建立執行緒池的數量
     */
    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    /**
     * Java 8 新增的執行緒池,具有搶佔式操作的執行緒池,每個執行緒都有一個任務佇列存放任務,
     * 當執行緒發現自己的佇列沒有任務了,也就是先工作完了的執行緒就去幫助沒處理完的執行緒工作。
     * 以實現最快完成工作。
     * 是基於 ForkJoinPool 建立的執行緒池,parallelism 引數自定義並行度。
     */
    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    /**
     * 同上,但是並行度是根據獲取當前系統的 CPU 核心數來判斷。
     */
    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    /**
     * 建立固定數量執行緒的執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
     * 多了一個 ThreadFactory 引數,執行緒工廠,主要用來建立執行緒池
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

    /**
     * 建立單個執行緒的執行緒池。它可以保證先進先出的執行順序。
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

    /**
     * 同上。
     */
    public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>(),
                                    threadFactory));
    }

    /**
     * 建立一個可快取的執行緒池。適用於短期執行的非同步任務,從程式碼中可以看出執行緒數的設定是
     * Integer.MAX_VALUE,不對執行緒池的大小做設定,可以建立無限數量的執行緒。
     * 但也就不適合執行長時間執行的任務,可能會導致系統資源耗盡。
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

    /**
     * 同上
     */
    public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>(),
                                      threadFactory);
    }

    /**
     * 建立一個單執行緒的可以執行延遲任務的執行緒池,可以安排以給定延遲後執行的命令或定時執行的命令。
     * 
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

    /**
     * 同上
     */
    public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1, threadFactory));
    }

    /**
     * 建立一個可以執行延遲任務的執行緒池,任務數量自定義
     */
    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    /**
     * 同上
     */
    public static ScheduledExecutorService newScheduledThreadPool(
            int corePoolSize, ThreadFactory threadFactory) {
        return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
    }
}

可以看到其實 Executors 建立的執行緒大部分都是由 ThreadPoolExecutor 實現。

ThreadPoolExecutor

直接看下他的建構函式:

public ThreadPoolExecutor(int corePoolSize, // 核心執行緒數,執行緒池中始終存活的執行緒數
                           // 最大執行緒數,執行緒池中允許的最大執行緒數
                          int maximumPoolSize,
                          // 最大執行緒數可以存活的時間
                          long keepAliveTime, 
                          // 時間單位
                          TimeUnit unit, 
                          // 阻塞佇列,workQueue 包含七種
                          BlockingQueue<Runnable> workQueue, 
                           // 執行緒工廠,主要用來建立執行緒
                          ThreadFactory threadFactory,
                          // 拒絕策略
                          RejectedExecutionHandler handler ) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
    this.prestartAllCoreThreads();
}

ThreadPoolExecutor 的執行原理如圖:

相關文章