爲了不重複的建立線程,線程池的出現可讓線程進行復用。通俗來說,當有任務提交時,就會向線程池拿一個線程,當任務完成後,並非直接關閉線程,而是將這個線程歸還給線程池供其餘任務使用。html
ThreadPoolExecutor是線程池的實現類。java
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.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}複製代碼
構造器參數解析:緩存
corePoolSize:線程池的核心池大小,在建立線程池以後,線程池默認沒有任何線程。除非調用了prestartAllCoreThreads()或prestartCoreThread()方法,這兩個方法是預建立線程的方法,即在沒有任務到來以前會建立corePoolSize個線程或者一個線程。默認狀況下,在建立了線程池後,線程池中的線程數爲0,當有任務提交,就會建立一個線程去執行任務,當線程池的線程數目達到corePoolSize後,就會把到達的任務放到緩存隊列中。bash
maximumPoolSize:線程池的最大線程數。若是阻塞隊列滿了,而且已建立的線程數小於最大線程數,則線程池會在建立新的線程執行。ui
keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認狀況下,當線程池中的線程數大於corePoolSize時,若是一個線程空閒時間達到keepAliveTime,線程則會終止,直到線程池中的線程數不大於corePoolSize。若是調用了allowCoreThreadTimeOut(boolean)方法,在線程池中的線程數不大於corePoolSize時,keepAliveTime參數也會起做用,直到線程池中的線程數爲0。this
unit:參數keepAliveTime的時間單位。spa
workQueue:阻塞隊列,用來存儲等待執行的任務。阻塞隊列通常有如下幾種:線程
ArrayBlockingQueue;//數組結構的有界阻塞隊列,先進先出,建立時必須指定大小
LinkedBlockingQueue;//鏈表結構的無界阻塞隊列,先進先出
SynchronousQueue;//不存儲元素的阻塞隊列,每次插入操做必須等到另外一個線程調用移除操做複製代碼
threadFactory:線程工廠,主要用來建立線程3d
handler:拒絕處理任務策略,有如下四種取值。
ThreadPoolExecutor.AbortFactory;//丟棄任務並拋出RejectedExecutionException異常
ThreadPoolExecutor.DiscardPolicy;//丟棄任務,但不拋出異常
ThreadPoolExecutor.DiscardOldestPolicy;//丟棄隊列最前面的任務,而後從新嘗試執行任務(重複此過程)
ThreadPoolExecutor.CallerRunsPolicy;//由調用線程處理該任務複製代碼
首先取得當前線程池中的線程總數,與核心池大小比較,
ThreadPoolExecutor提供了兩個方法關閉線程池:
shutdown();//不會當即終止線程池,等全部的任務和阻塞隊列的任務都執行完才終止,但再也不接受新的任務。
shutdownNow();//當即終止線程池,並嘗試打斷正在執行的任務,並清空阻塞隊列,返回還沒有執行的任務複製代碼
volatile int runState;
static final int RUNNING = 0;//運行狀態
static final int SHUTDOWN = 1;//關閉狀態
static final int STOP = 2;//中止
static final int TERMINATED = 3;//終止複製代碼
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}複製代碼
固定大小的線程池,該線程池corePoolSize和maximumPoolSize相等,阻塞隊列爲LinkedBlockingQueue。固定大小的線程池,不存在線程數量的變化。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}複製代碼
單線程線程池,只有一個線程的線程池,阻塞隊列用LinkedBlockingQueue,如有多餘的任務提交到線程池中,則會被暫存到阻塞隊列,等空閒時再去執行,按照先進先出的順序執行。該線程池可保證任務按照被加入順序執行。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}複製代碼
緩存線程池,緩存的線程默認存活60秒。線程池的corePoolSize大小爲0,最大線程數爲Integer.MAX_VALUE,阻塞隊列使用的是SynchronousQueue,是一個直接提交的阻塞隊列,它總會迫使線程池增長新的線程去執行任務。當線程的空間時間超過60s,則工做線程將會終止被回收。當提交新任務時,若是沒有空閒線程,則建立新線程執行任務。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}複製代碼
定時線程池,可用於週期性地執行任務,一般用於週期性的同步數據。