继上一篇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性能优化,先准备下基本知识。