1. 程式人生 > 其它 >Java 執行緒池使用 Executors 與 ThreadPoolExecutor

Java 執行緒池使用 Executors 與 ThreadPoolExecutor

參考

介紹

Executors 工具類建立執行緒實現是呼叫的 ThreadPoolExecutor,但是隱藏了部分細節和引數設定。並且阿里巴巴程式碼規範也禁止使用 Executors 工具類建立執行緒池。

建立方法 描述
Executors 工具類三種方法建立執行緒 堵塞等待執行(這裡不確定,可能有其他方法可以指定策略來堵塞或拋棄任務)
ThreadPoolExecutor 根據配置的拒絕策略來執行

Executors 方法

方法名 描述
Executors.newSingleThreadExecutor() 單一執行緒
Executors.newFixedThreadPool(int nThreads) 指定執行緒數量
Executors.newCachedThreadPool() 無限制,自動擴容與縮容(最大21億)

ThreadPoolExecutor 介紹

  1. 引數列表

    引數名 描述
    int corePoolSize 核心執行緒數(不會被關閉)
    int maximumPoolSize 最大執行緒數(當佇列滿了之後,就會適當開啟執行緒)
    long keepAliveTime 當前執行緒數大於核心執行緒數,並且某些執行緒空閒一定時間後,會被關閉
    TimeUnit unit 超時時間單位
    BlockingQueue workQueue 指定使用的阻塞佇列型別與設定佇列的大小
    ThreadFactory threadFactory 執行緒工廠,主要用來建立執行緒,預設為正常優先順序、非守護執行緒
    RejectedExecutionHandler handler 拒絕策略,有四種
  2. 拒絕策略

    策略名 描述
    ThreadPoolExecutor.AbortPolicy 滿了(最大執行緒數+佇列大小)就報錯,但是已經進入的任務會執行完畢,這裡 shutdown() 方法要放在 finally 中
    ThreadPoolExecutor.CallerRunsPolicy 滿了(最大執行緒數+佇列大小)拒絕/丟棄,直接在execute方法的呼叫執行緒中執行被拒絕的任務(main執行緒)
    ThreadPoolExecutor.DiscardOldestPolicy 滿了(最大執行緒數+佇列大小)就拒絕/丟棄最早進入並且未處理的任務
    ThreadPoolExecutor.DiscardPolicy 滿了就拒絕/丟棄

Executors 不推薦

package pool;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * @Author 夏秋初
 * @Date 2022/3/3 14:22
 */
public class Test {
    public static void main(String[] args) {
        // 單一執行緒
//        ExecutorService executorService = Executors.newSingleThreadExecutor();
        // 固定執行緒數量
//        ExecutorService executorService = Executors.newFixedThreadPool(2);
//         最大21億
        ExecutorService executorService = Executors.newCachedThreadPool();

        for (int i = 0; i < 10; i++) {
            executorService.execute(()->{
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            });
        }
        // 必須手動關閉
        executorService.shutdown();
    }
}

ThreadPoolExecutor 推薦

package pool;

import java.util.concurrent.*;

/**
 * @Author 夏秋初
 * @Date 2022/3/3 14:22
 */
public class Test2 {
    public static void main(String[] args) {
        // 執行緒池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                // 核心執行緒數(不會被關閉)
                2,
                // 最大執行緒數(當佇列滿了之後,就會適當開啟執行緒)
                5,
                // 當前執行緒數大於核心執行緒數,並且某些執行緒空閒一定時間後,會被關閉
                10,
                // 超時時間單位,當前例子是 10s
                TimeUnit.SECONDS,
                // 指定使用的阻塞佇列型別與設定佇列的大小
                new LinkedBlockingDeque<Runnable>(3),
                // 執行緒工廠,主要用來建立執行緒,預設為正常優先順序、非守護執行緒
                Executors.defaultThreadFactory(),
                /**
                 * 拒絕策略
                 * ThreadPoolExecutor.AbortPolicy 滿了就報錯,但是已經進入的任務會執行完畢,這裡 shutdown() 方法要放在 finally 中
                 * ThreadPoolExecutor.CallerRunsPolicy 滿了丟棄,直接在execute方法的呼叫執行緒中執行被拒絕的任務
                 * ThreadPoolExecutor.DiscardOldestPolicy 滿了就丟棄最早進入並且未處理的任務
                 * ThreadPoolExecutor.DiscardPolicy 滿了就丟棄
                 */
                new ThreadPoolExecutor.DiscardOldestPolicy()
        );

        try{
            for (int i = 0; i < 20; i++) {
                final int temp = i;
                threadPoolExecutor.execute(()->{
                    try {
                        TimeUnit.SECONDS.sleep(3);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"  "+temp);
                });
            }
        }finally {
            // 必須手動關閉
            threadPoolExecutor.shutdown();
        }
    }
}

如果覺得文章對您有幫助,希望您能 關注+推薦 哦