Java執行緒池詳解

2023-01-31 12:00:27

一、執行緒池有哪些優點

  1. 減少資源開銷,不用頻繁的建立和銷燬執行緒
  2. 提高響應時長,有任務時可直接執行。
  3. 提高執行緒的可管理性,所有執行緒資源都由執行緒池統一管理。

二、執行緒池的主要引數

執行緒池ThreadPoolExecutor的繼承關係:


想知道有哪些引數,先看引數最多的建構函式:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    if (corePoolSize < 0 ||
        maximumPoolSize <= 0 ||
        maximumPoolSize < corePoolSize ||
        keepAliveTime < 0)
        throw new IllegalArgumentException();
    if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
    this.corePoolSize = corePoolSize;
    this.maximumPoolSize = maximumPoolSize;
    this.workQueue = workQueue;
    this.keepAliveTime = unit.toNanos(keepAliveTime);
    this.threadFactory = threadFactory;
    this.handler = handler;
}

可以看到建立一個執行緒池需要七個引數。

  1. corePoolSize:執行緒池核心執行緒數量大小,有新任務進來時,如果執行緒池中的執行緒數小於這個值,則會建立新的執行緒來執行任務(不管有沒有空閒執行緒,都會建立),直到執行緒數量大於等於這個數量。
  2. maximumPoolSize:執行緒池最大執行緒數量大小(當達到核心執行緒數,且佇列任務已滿,會增加執行緒至最大執行緒數)。
  3. keepAliveTime:執行緒的最大空餘時間,大於這個時間將被回收(執行緒數大於核心執行緒數時,多餘的執行緒空閒時長達到這個值就會被回收)。
  4. unit:空餘時長的單位。
  5. workQueue:阻塞佇列,當核心執行緒數已滿,任務會被放到這個佇列中。
  6. threadFactory:執行緒工廠,執行緒池中的執行緒都是由這個執行緒工廠建立的,執行緒池提供了預設的執行緒工廠。
  7. handler:拒絕策略,當佇列任務已滿,且執行緒數量達到最大執行緒數,新進入的任務會執行這個拒絕策略來選擇丟棄哪個任務,執行緒池提供了四種預設的拒絕策略。

執行緒工廠ThreadFactor,執行緒池中預設給定了一個執行緒工廠DefaultThreadFactory,執行緒工廠的作用是用於建立執行緒,自己建立執行緒工廠時需要實現ThreadFactor介面,該介面中只有一個方法Thread newThread(Runnable r);,即建立執行緒的方法,自定義執行緒工廠的好處是可以自定義執行緒名稱。

阻塞佇列BlockingQueue,阻塞佇列是在核心執行緒滿了以後存放任務使用,常用的有LinkedBlockingQueueArrayBlockingQueueSynchronousQueueDelayedWorkQueue等,當阻塞佇列也滿時,會建立執行緒至最大執行緒數,如果佇列已滿,也達到最大執行緒數,則執行拒絕策略。

拒絕策略RejectedExecutionHandler

  • DiscardPolicy:丟棄該任務,不拋異常。
  • DiscardOldestPolicy:丟棄最早加入佇列的任務,不拋異常。
  • AbortPolicy:丟棄該任務並丟擲異常RejectedExecutionException,預設使用該策略。
  • CallerRunsPolicy:由呼叫執行緒池的執行緒來執行當前任務。

檢視原始碼:

public static class DiscardPolicy implements RejectedExecutionHandler {
    public DiscardPolicy() { }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    }
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    public DiscardOldestPolicy() { }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            e.getQueue().poll();
            e.execute(r);
        }
    }
}
public static class AbortPolicy implements RejectedExecutionHandler {
    public AbortPolicy() { }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                                             " rejected from " +
                                             e.toString());
    }
}
public static class CallerRunsPolicy implements RejectedExecutionHandler {
    public CallerRunsPolicy() { }
    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
            r.run();
        }
    }
}

如果想要實現自己的拒絕策略,那麼實現RejectedExecutionHandler介面即可。

三、執行緒池的執行流程

如下圖:

五、Java提供的快速建立的執行緒池

Executors提供了幾種快速建立的執行緒池:

  • newSingleThreadExecutor,只有一個執行緒的執行緒池
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
  • newFixedThreadPool,固定執行緒數量的執行緒池
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • newCachedThreadPool,可快取的執行緒池,即不限制執行緒數量的執行緒池。
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  • newScheduledThreadPool,定時執行緒池,可週期性或延遲執行任務的執行緒池(使用延時佇列)。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
          new DelayedWorkQueue());
}
  • newSingleThreadScheduledExecutor,單個執行緒的定時執行緒池,功能和上面一樣。
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
    return new DelegatedScheduledExecutorService
        (new ScheduledThreadPoolExecutor(1));
}

六、最後

歡迎關注個人微信公眾號