由於線程的頻繁調度,而影響性能,通過線程池來維護,減少線程的頻繁的創建和銷燬。
在Executors統一管理,看一下常見的四中線程池:
1.newFixedThreadPool:創建定長的線程池,超出定長在線程隊列中等待。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
2.newCachedThreadPool:線程數無限大,當線程隊列中有空閒線程時會複用,否則重新創建線程,同時線程60s沒有用時,從線程隊列中移除。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
3.newScheduledThreadPool:次線程池是在規定的時間進行調度。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
4.newSingleThreadExecutor:僅有一個線程在調度,且有順序的進行出隊和入隊。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
但是他們都調用了ThreadPoolExecutor:看一下核心構造器裏的幾個參數
corePoolSize: 要保留在池中的線程數量。
maximumPoolSize:線程池中允許的最大線程數。
keepAliveTime:空閒線程等待的最大時間。
unit:keepAliveTime的時間單位。
workQueue:可執行的任務隊列。
threadFactory:執行創建一個新的線程時使用。
handler:當達到了線程邊界和隊列容量,執行被阻塞時使用的處理程序。
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;
}
線程池中常用幾個方法源碼:
看一下runState控制得幾種狀態:
RUNNING: 接受新任務並能夠對添加的任務處理。
SHUTDOWN: 不接受新任務,但能處理已在隊列中的任務。
STOP: 不接受新任務,不處理排隊的任務,並同時中斷正在進行的任務。
TIDYING: 所有任務全部中斷,同時將workerCount 置0,並將所有線程切換到TIDYING狀態,會執行鉤子函數terminated()。
TERMINATED: 表示線程池徹底終止。執行完terminated()之後,就會由 TIDYING -> TERMINATED。
線程池的幾種轉態轉換:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();//保證了數據的原子性,不被其他線程干擾
if (workerCountOf(c) < corePoolSize) {//運行的線程數小於corePoolSize的數量時
if (addWorker(command, true))//添加一個新的到任務中
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {//插入任務成功且是Running狀態下
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))//移除任務成功且不是Running狀態下
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//如果添加到任務中失敗,拋出異常。
else if (!addWorker(command, false))
reject(command);
}
這裏addWorker(Runnable firstTask, boolean core)中的兩個參數:
firstTask:新線程首要運行。
core:用一個布爾值判斷當前線程數是否小於corePoolSize或maximumPoolSize。在源碼中
wc >= (core ? corePoolSize : maximumPoolSize))
shutdown()方法:對以前的任務切換到SHUTDOWN狀態,不接受新的任務。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;//重入鎖
mainLock.lock();
try {
checkShutdownAccess();//判斷調用者是否有權限shutdown線程池
advanceRunState(SHUTDOWN);//線程池狀態切換爲SHUTDOWN
interruptIdleWorkers();//中斷可能正在等待任務的線程
onShutdown(); // SHUTDOWN轉態下的進一步清理。但是使用了ScheduledThreadPoolExecutor取消延遲的任務。
} finally {
mainLock.unlock();
}
tryTerminate();//試着終止線程池
}