Java執行緒池之ThreadPoolExecutor

武臘福發表於2018-12-19

針對android中的多執行緒請求,本文主要介紹 android中執行緒池的基本使用。

1:執行緒池的分類

FixedThreadPool:它是一種執行緒數量固定的執行緒池,當執行緒處於空閒狀態時,它們並不會被回收,除非執行緒池被關閉,當所有的執行緒都處於活動狀態時,新任務都會處於等待狀態,直到有執行緒空閒出來。該執行緒池中只有核心執行緒,並且這些核心執行緒不會被回收,這意味著它能夠更加快速的響應外界的請求。
CachedThreadPool: 該執行緒池中執行緒數量不固定,並且內部只有非核心執行緒,其執行緒的最大值為 Integer.MAX_VALUE。所以可以認為該執行緒池中的執行緒數量可以任意大。該執行緒池的特定是當執行緒池中的執行緒都處於活動狀態時,執行緒池會建立新的執行緒來處理新的任務,否則就會利用空閒的執行緒來處理新的任務。該執行緒池中的空閒執行緒都有超時機制,這個超時時長為 60s ,超過60s 空閒執行緒就會被回收。
ScheduledThreadPool: 該執行緒池中包含核心執行緒以及非核心執行緒,核心執行緒數量是固定的,而非核心執行緒數量是沒有限制的,並且當非核心執行緒閒置時會被立即回收。
SingleThreadExecutor:該執行緒池是一個單例執行緒,其內部只有一個核心執行緒。

2:執行緒池的基本使用

FixedThreadPool:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4)
fixedThreadPool.execute(runnable)複製程式碼

CachedThreadPool:

 ExecutorService cacheThreadPool = Executors.newCachedThreadPool()
 cacheThreadPool.execute(runnable)複製程式碼

ScheduledThreadPool:

 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4)
 scheduledThreadPool.schedule(runnable3, 2000, TimeUnit.MILLISECONDS)複製程式碼

SingleThreadExecutor:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor()
singleThreadExecutor.execute(runnable)複製程式碼

2:執行緒池的基本使用

FixedThreadPool:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4)
fixedThreadPool.execute(runnable)複製程式碼

CachedThreadPool:

 ExecutorService cacheThreadPool = Executors.newCachedThreadPool()
 cacheThreadPool.execute(runnable)複製程式碼

ScheduledThreadPool:

 ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4)
 scheduledThreadPool.schedule(runnable3, 2000, TimeUnit.MILLISECONDS)複製程式碼

SingleThreadExecutor:

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor()
singleThreadExecutor.execute(runnable)複製程式碼

3: 執行緒池構造解析

android中執行緒池概念來源於java中的Executor,而Executor通過原始碼我們可以看出是一個介面;

public interface Executor {
    void execute(Runnable command);
}
複製程式碼

內部只包含一個抽象方法 execute(….);

同時android中 重新定義了ExecutorService介面去繼承上述介面;

public interface ExecutorService extends Executor{}複製程式碼

而 ExecutorService 介面的實現類是:

public abstract class AbstractExecutorService implements ExecutorService{}複製程式碼

抽象類AbstractExecutorService 的具體實現是:

public class ThreadPoolExecutor extends AbstractExecutorService{}複製程式碼

通過上述關係可以看到執行緒池的真正實現為ThreadPoolExecutor,在ThreadPoolExecutor 中提供了一系列的引數來建立不同的執行緒池。
下面我們來看ThreadPoolExecutor的建構函式:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {}複製程式碼

內部引數:

corePoolSize:執行緒的核心執行緒數;
maximumPoolSize:執行緒池所能容納的最大執行緒數:
keepAliveTime:非核心執行緒閒置時的超時市場,超過這個時長非核心執行緒就會被回收
unit:用於指定keepAliveTime 的單位
workQueue:執行緒池中的任務佇列
threadFactory:執行緒工廠,為執行緒池提供建立新執行緒的功能
handler:當執行緒池無法執行新的任務時,會呼叫handler的rejectedEcexutor方法來通知呼叫者。該引數不常用,可以忽略。
通過原始碼我們可以看到google是通過工廠方式去建立各種執行緒池,具體原始碼我們可以通過

public class Executors{}複製程式碼

該類可以看到內部通過各種方法去獲取不同的執行緒池。

下面我們根據Executors 中各個方法去看各個執行緒池是如何實現的。

FixedThreadPool:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue());
    }複製程式碼

FixedThreadPool 通過呼叫 ThreadPoolExecutor建構函式 可以看出實質上是通過外部設定了 核心執行緒數,以及非核心執行緒數。
CachedThreadPool:

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue());
    }複製程式碼

CachedThreadPool 內部可以看出實質上 核心執行緒數為0 ,而非核心執行緒數為Int最大值
SingleThreadExecutor:

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }複製程式碼

SingleThreadExecutor 可以看出實質上是核心執行緒數以及非核心執行緒數均為1;

ScheduledThreadPool:

 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }


public class ScheduledThreadPoolExecutor
        extends ThreadPoolExecutor
        implements ScheduledExecutorService {
        ....
         public ScheduledThreadPoolExecutor(int corePoolSize) {
                super(corePoolSize, Integer.MAX_VALUE,
                      DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
                      new DelayedWorkQueue());
            }
            ....
    }複製程式碼

ScheduledThreadPool 可以看出核心執行緒數是通過外部設定,而非核心執行緒數實質是int的最大值。

4 : 執行緒池的基本執行流程

1:如果執行緒池中核心執行緒未達到上限那麼,則會直接啟動一個核心執行緒去執行任務;
2:如果核心執行緒達到上限,那麼會將任務放到任務佇列中,等待執行,
3:如果任務無法插入到任務佇列中,則會開啟一個非核心執行緒去執行任務,
4:如果執行緒池中的執行緒已經達到執行緒數量的上限,則將不會去執行任務,ThreadPoolExecutor將會呼叫RejectedExecutionHandler的rejectedExecution方法通知呼叫者。

以下通過圖示來說明:

這裡寫圖片描述


相關文章