ThreadPoolExecutor執行緒池原始碼解讀keepAliveTime 空閒過期時間作用
keepAliveTime引數主要是把除了核心執行緒 其他執行緒當超過等待時間keepAliveTime 就會進行執行緒移除 接下來主要講下執行緒是如何建立 執行 然後操作等待時間是如何移除的 先介紹兩個執行緒池的核心引數
- HashSet workers工作類集合
Worker這個其實就是儲存線上程池裡的執行緒 實現了Runnable介面 當執行緒池中開啟10個執行緒 就會建立10個Worker類 這些worker會儲存在workers工作類集合中 Worker類裡面主要有一下兩個核心引數
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
/** 執行Worker的執行緒 */
final Thread thread;
/** 這裡存放的是使用方傳給執行緒池的執行緒 */
Runnable firstTask;
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
// 把自己本身worker放入到thread中 後面直接執行thread.start 就會執行Worker的run方法 然後在run方法中執行firstTask.run
this.thread = getThreadFactory().newThread(this);
}
複製程式碼
- BlockingQueue< Runnable > workQueue 等待佇列
這個其實就是當執行緒達到核心執行緒數以後 會把待執行的佇列放入到等待佇列中等待執行
execute(Runnable command)
當第一次執行執行緒池的execute 會因為當前執行緒數小於核心執行緒數而執行這段程式碼 當然核心執行緒數設定為0除外
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command,true))
return;
c = ctl.get();
}
複製程式碼
這裡核心是addWorker方法 這裡會把傳進來當需要執行的執行緒command放入到剛剛說的worker工作類中 然後再放入到workers工作類集合中 然後啟動worker執行緒
//只拉取核心程式碼
// firstTask為execute(Runnable command)傳入的需要執行的執行緒
w = new Worker(firstTask);
final Thread t = w.thread;
workers.add(w);
t.start();
複製程式碼
之後看下Worker的run方法 裡面會先執行runWorker方法 然後在方法中執行需要執行的執行緒 這裡核心主要程式碼有兩句
//task為前面execute(Runnable command)傳入的需要執行的執行緒 如果不為空則執行執行task.run 如果為空 則通過getTask() 獲取等待佇列workQueue裡需要執行的執行緒
while (task != null || (task = getTask()) != null)
複製程式碼
重點 keepAliveTime的體現核心就是getTask()方法中
當前執行的執行緒是核心執行緒 則timed=false
//只拉取核心程式碼
Runnable r = timed ?
workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) :
workQueue.take();
複製程式碼
就會執行workQueue.take()從等待佇列裡獲取一個需要執行的執行緒任務 因為 BlockingQueue< Runnable > workQueue是阻塞佇列 如果裡面沒有需要執行的執行緒任務 則會一直阻塞等待 一直到獲取執行緒任務
workQueue.take();
複製程式碼
重點 如果timed=true 執行workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) : keepAliveTime就是在這裡發揮作用的
poll這行程式碼就是會等待keepAliveTime設定的時間 超過超時時間就返回null
workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) :
複製程式碼
當超過超時時間 getTask就會返回null
while (task != null || (task = getTask()) != null)
複製程式碼
推出迴圈 並且設定
completedAbruptly = false;
複製程式碼
然後執行processWorkerExit方法
processWorkerExit(w,completedAbruptly)
複製程式碼
processWorkerExit這裡核心就是把當前執行的worker從worker工作類集合中刪除
workers.remove(w);
複製程式碼
然後還有一段邏輯
if (!completedAbruptly) {
//allowCoreThreadTimeOut預設為false 如果設定為true 則代表執行緒池中corePoolSize執行緒空閒時間達到keepAliveTime也將關閉 上面說的timed 如果allowCoreThreadTimeOut為true 則timed也會為true 也就會進入poll方法 通過這個來實現超時關閉核心執行緒數
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
if (min == 0 && ! workQueue.isEmpty())
min = 1;
//當前執行緒數大於核心執行緒數 直接返回 然後執行緒關閉
if (workerCountOf(c) >= min)
return; // replacement not needed
}
addWorker(null,false);
複製程式碼
注意上面的 addWorker(null,false); 這個其實是個注意點優化點 當執行一開始自己寫的Runnable command 的run方法如果執行異常 也會走上面的程式碼completedAbruptly=true 然後執行addWorker(null,false); 建立一個空的worker執行緒繼續執行