线程池
Java中,有两个主流的线程池实现,分别为ThreadPoolExecutor和ScheduledThreadPoolExecutor。它们的继承关系如下:
ExecutorService <----- AbstractExecutorService <------ ThreadPoolExecutor <----- ScheduledThreadPoolExecutor
ScheduledExecutorService <----- ScheduledThreadPoolExecutor
ThreadPoolExecutor支持execute(...)方法,ScheduledThreadPoolExecutor额外支持schedule(...)方法。
ThreadPoolExecutor
先来看线程池内部的一些变量。
- BlockingQueue<Runnable> workQueue : 暂时保存不能立刻执行的任务
- HashSet<Worker> workers = new HashSet<Worker>()
- Worker相当于对Thead的状态,占据一个线程,连续处理多个任务
- int poolSize: 当前存在的线程的数目
- int corePoolSize : 核心的线程数目
- 线程池会尽量保持corePoolSize个线程(可能少于)。当poolSize大于corePoolSize时,除非逼不得已,否则不会创建线程,而是将线程存入等待队列。
- int maximumPoolSize: 最多的线程数目,也即不管咋样,不能超过这么多线程。
- int runState: 当前的状态(状态变化见图),尤其注意状态都是不可逆的。
- RUNNING: 可以接受新的任务,并执行现有的任务。
- SHUTDOWN: 不可以接受新的任务,但是可以执行现有的任务。
- STOP: 不可以接受新的任务,不再执行队列中的任务,中断了所有正在执行的任务。
- TERMINATED: 所有线程都终结了。
- ReentrantLock mainLock = new ReentrantLock()
- 用来保护:poolSize, corePoolSize, maximumPoolSize, runState, and workers
添加新任务
当添加新任务时,线程池会尝试立刻执行此任务,或者将任务放入队列中等待以后执行,否则会调用RejectedExecutionHandler.rejectedExecution拒绝任务。
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
if (poolSize >= corePoolSize // 超过核心线程数目,则肯定不能立刻执行
|| !addIfUnderCorePoolSize(command) // [线程安全]尝试立刻执行任务
) {
if (runState == RUNNING && workQueue.offer(command)) { // 如果当前状态时RUNNING(可以接受新任务),则尝试把命令放入队列
// 再次验证此任务,有可能在offer的同时,线程池中的线程全部执行完毕并退出了,从而导致此任务不被处理,所以要再次验证一下。
if (runState != RUNNING // 线程池被关闭了,则应该拒绝此任务(其实也可以不拒绝?)
|| poolSize == 0) // 线程池空了,则应该启用一个线程,以执行此任务(这是主要的)
ensureQueuedTaskHandled(command); // [线程安全]拒绝任务或者保证有一个线程执行此任务
}
else if (!addIfUnderMaximumPoolSize(command))// [线程安全]尝试创建新的线程来允许此任务,此操作会导致poolSize大于corePoolSize。
reject(command);
}
}
从中可以看到
- 如果workQueue是无限的,则poolSize是不会大于corePoolSize的。
- 每一个路径下,最后总是一个线程安全的。这些线程安全的方法保证了每个新任务要么被立刻执行,要么被放入队列,要么被拒绝。
任务的执行
ThreadPoolExecutor.Worker对Thread进行了包装,是任务执行的实际类。
public void run() {
try {
Runnable task = firstTask;
firstTask = null;
while (task != null || (task = getTask()) != null) { // 获取任务
runTask(task); // 执行任务
task = null;
}
} finally {
workerDone(this);
}
}
Future
每个任务在提交后,可以返回Future对象,用来代表并行计算的结果。可以通过Future对象来取消任务,等待任务执行完毕,获取任务的返回值等。
在AbstractExecutorService中
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask); // 即上面提到的execute方法
return ftask;
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
FutureTask的代码是:
public class FutureTask<V> implements RunnableFuture<V> {
// 同步控制
private final Sync sync;
// ....
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
从上面的代码可以了解到,Future
的实现是通过对传入的Runnable
任务封装成RunnableFuture
任务,从而可以有额外的接口来控制或监控任务(比如取消,等待任务完成等)。FutureTask
中会把实际的逻辑委托给Sync子类完成。Sync
继承自AbstractQueuedSynchronizer
,是具备线程安全保证的。
private final class Sync extends AbstractQueuedSynchronizer {
// private volatile int state;// 在父类中被声明
// 表示正在运行(0表示等待运行,未被作为常量声明)
private static final int RUNNING = 1;
// 表示已经运行了
private static final int RAN = 2;
// 表示被取消运行
private static final int CANCELLED = 4;
// 用户提交的任务
private final Callable<V> callable;
// 任务的返回值
private V result;
// 任务执行期间抛出的异常
private Throwable exception;
// runner表示运行任务的线程。
// 当set或者cancel后,runner会被赋值为null,标志着可以使用result对象或exception异常(也即任务正式结束)。
// 之所以使用runner,而不是state,是因为state是通过compareAndSet方式设置的,
// 这种方式要求:必须在state成功设置成RAN后,才能给result赋值,从而不能通过state来判断result对象是否可用。
private volatile Thread runner;
Sync(Callable<V> callable) {
this.callable = callable;
}
private boolean ranOrCancelled(int state) {
// 使用位操作来快速判断,等价于state == RAN || state == CANCELLED。
// 之所以不采用此形式,是因为有两个等于判断,不是线程安全的。
return (state & (RAN | CANCELLED)) != 0;
}
boolean innerIsCancelled() {
return getState() == CANCELLED;
}
boolean innerIsDone() {
// runner为null才标识着任务的正式结束
return ranOrCancelled(getState()) && runner == null;
}
// 尝试获取锁:任务完成返回1,否则返回-1。
@Override
protected int tryAcquireShared(int ignore) {
return innerIsDone()? 1 : -1;
}
// 释放锁,设置runner为null,标记任务完成
protected boolean tryReleaseShared(int ignore) {
runner = null;
return true;
}
V innerGet() throws InterruptedException, ExecutionException {
// 获取锁,内部会调用tryAcquireShared方法,当其返回值>=0时,才表示成功获取锁
acquireSharedInterruptibly(0);
// 此时,任务应该已经成功完成,state应该不会再变化
// 如果state为CANCELLED,表示任务被取消,抛出CancellationException异常
if (getState() == CANCELLED)
throw new CancellationException();
// 否则state为RAN(见ranOrCancelled方法),表示任务成功执行完毕,
// 先判断是否有执行异常,否则直接返回任务的返回值
if (exception != null)
throw new ExecutionException(exception);
return result;
}
// 与innerGet()类似
V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
if (!tryAcquireSharedNanos(0, nanosTimeout))
throw new TimeoutException();
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
return result;
}
// 设置任务的返回值
void innerSet(V v) {
// compareAndSet方式对state赋值
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
// 此时s==RUNNING或者0
if (compareAndSetState(s, RAN)) {
// state成功设置为RAN后,才能对result复制
result = v;
// releaseShared会调用tryReleaseShared,从而设置runner为null
releaseShared(0);
done();
return;
}
}
}
// 与innerSet(V v)类似
void innerSetException(Throwable t) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
if (compareAndSetState(s, RAN)) {
exception = t;
result = null;
releaseShared(0);
done();
return;
}
}
}
// 取消任务执行,mayInterruptIfRunning表示中断runner
boolean innerCancel(boolean mayInterruptIfRunning) {
for (;;) {
int s = getState();
if (ranOrCancelled(s))
return false;
// 此时state只能为0或RUNNING
if (compareAndSetState(s, CANCELLED))
break;
}
// 如有必要,中断线程
if (mayInterruptIfRunning) {
Thread r = runner;
if (r != null)
r.interrupt();
}
releaseShared(0);
done();
return true;
}
// 开始执行任务
void innerRun() {
// 0表示初始状态,先尝试把state设置为RUNNING
if (!compareAndSetState(0, RUNNING))
return;
try {
runner = Thread.currentThread();
// 会再次检查state的状态,检查的目的是防止无意义地调用callable.call()。
if (getState() == RUNNING)
innerSet(callable.call());
else
releaseShared(0); // cancel
} catch (Throwable ex) {
innerSetException(ex);
}
}
// 执行任务,执行完毕后,标记任务为初始状态。只有当任务被调度为重复运行时,才会调用此方法。
// 由于是重复运行,所以不设置result值,Future的get方法也无定义。
boolean innerRunAndReset() {
if (!compareAndSetState(0, RUNNING))
return false;
try {
runner = Thread.currentThread();
if (getState() == RUNNING)
callable.call(); // don't set result
runner = null;
return compareAndSetState(RUNNING, 0);
} catch (Throwable ex) {
innerSetException(ex);
return false;
}
}
}