繼上一篇java-線程池(一)講解了線程池的好處及常用線程池,這篇解析線程池源碼。
線程池重點類如下
Executor |
接口,僅execute方法,將任務放入線程池 |
ExecutorService |
接口,繼承Executor,增加對線程的狀態獲取 |
Executors |
類,任務提交和線程池類別選擇 |
ThreadPoolExecutor |
類,線程池,負責對任務的調度和處理 |
(一)Executor
public interface Executor {
/**
* 將線程放入線程池
* @param command 要執行的異步任務
*/
void execute(Runnable command);
}
統一提供線程提交接口,所有線程池生成都必須繼承。
public interface ExecutorService extends Executor {
void shutdown();
boolean isShutdown();
boolean isTerminated();
<T> Future<T> submit(Callable<T> task);
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
// 省略部分方法
}
在Executor的基礎上,添加對線程的生命週期的控制(終止、喚醒等)
(三)Executors
將線程池的任務提交和執行分離,此部分是任務提交部分,提供四種基本的線程池。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
corePoolSize |
maximumPoolSize |
keepAliveTime |
workQueue |
|
---|---|---|---|---|
newFixedThreadPool |
nThreads |
nThreads |
0L |
LinkedBlockingQueue |
newSingleThreadExecutor |
1 | 1 | 0L | LinkedBlockingQueue |
newCachedThreadPool |
0 | Integer.MAX_VALUE |
60L | SynchronousQueue |
newScheduledThreadPool |
corePoolSize |
Integer.MAX_VALUE |
0L |
DelayedWorkQueue |
corePoolSize:線程池維護線程的最小數量
maximumPoolSize:線程池維護的最大線程數量
keepAliveTime:線程銷燬保留時間
workQueue:使用的任務保存隊列
newFixedThreadPool定長線程,可固定最大線程數。
newSingleThreadExecutor提供單線程線程池,適合按順序執行任務。
newCachedThreadPool提供了線程銷燬緩衝期60L,最大線程數無上限,適合大量小任務執行。
(四)ThreadPoolExecutor
/**
* 核心方法,任務丟給線程池
* @param command
*/
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
// 如果線程數小於基本線程數,則創建線程並執行當前任務
if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
// 如線程數大於等於基本線程數或線程創建失敗,則將當前任務放到工作隊列中。
if (runState == RUNNING && workQueue.offer(command)) {
//若當前沒任何線程執行,強制開始首個線程任務
if (runState != RUNNING || poolSize == 0)
ensureQueuedTaskHandled(command);
}
// 如果線程池不處於運行中或任務無法放入隊列,並且當前線程數量小於最大允許的線程數量,則創建一個線程執行任務。
else if (!addIfUnderMaximumPoolSize(command))
// 當任務無法成功接收時,按策略做異常處理
reject(command);
}
}
/**
* 添加任務到線程池
* @param firstTask
* @return
*/
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//線程數未滿基本線程數且當前是運行狀態時,開啓新線程
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
return t != null;
}
/**
* 給任務開啓一個線程
*
* @param firstTask
* @return
*/
private Thread addThread(Runnable firstTask) {
//worker代表一個線程,有對整個線程的處理,當前任務執行完,自動拿隊列任務執行
Worker w = new Worker(firstTask);
//工廠模式創建線程
Thread t = threadFactory.newThread(w);
boolean workerStarted = false;
if (t != null) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
w.thread = t;
workers.add(w);
int nt = ++poolSize;
//當前線程數已達最大數時,不再開啓新線程
if (nt > largestPoolSize)
largestPoolSize = nt;
try {
t.start();
workerStarted = true;
}
finally {
if (!workerStarted)
workers.remove(w);
}
}
return t;
}
(五)線程池學習概要
線程池的合理運用,能提升系統性能,線程池創建有四種類型,各有利弊,具體情況具體分析。
後面會有專題講解android性能優化,先準備下基本知識。