FutureTask 是一个可以被取消的异步。它实现了Future接口中的方法(获取任务执行结果方法、取消任务的方法)。在获取执行结果的过程中,如果当前任务没有完成会阻塞。提供两种方式获取执行结果,一种无限期等待直到任务完成,另一种设置超时时间,在超时时间内没有获取到结果则直接返回,防止一直阻塞。
FutureTask 实现了RunnableFuture接口,RunnableFuture接口糅合了Runnable接口和Future接口,如下图是FutureTask类的继承关系:
通过上图可以清晰的看出,FutureTask类实现了RunnableFuture接口,在内部创建了WaitNode类,主要存储等待线程信息。因为获取执行结果是阻塞式获取,会将这些信息存放到WaitNode中。
report 方法自己内部调用,返回任务的执行结果。会判断当前任务是否取消
// 私有方法给自己使用,传入当前FutureTask的状态,返回任务的执行结果
private V report(int s) throws ExecutionException {
// 获取执行结果
Object x = outcome;
// 判断当前任务是否结束
if (s == NORMAL)
// 将结果信息转化为传入的类型
return (V)x;
// 当前任务被取消
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
FutureTask 构造方法提供两种方式,一种传入Callable任务类型,一种传入Runnable类型任务
// 传入callable类型的任务,callable类型任务带返回值,不会包装对应的返回值结果
public FutureTask(Callable<V> callable) {
// 判断是否为空
if (callable == null)
throw new NullPointerException();
this.callable = callable;
// 设置当前任务状态为新建状态
this.state = NEW;
}
// 传入Runnable类型的任务,并传入返货结果。因Runnable无返回值所以需要传入
public FutureTask(Runnable runnable, V result) {
// 封装为Callable类型
this.callable = Executors.callable(runnable, result);
// 设置当前任务为新建状态
this.state = NEW;
}
此方法返回当前任务是否被取消
public boolean isCancelled() {
// 判断当前任务状态,任务状态为取消
return state >= CANCELLED;
}
判断任务是否被执行
public boolean isDone() {
// 任务被执行当前状态不为新建状态
return state != NEW;
}
取消当前线程的执行,mayInterruptIfRunning用户指定,是否中断正在执行的任务,如果传入为true则中断正在执行的任务。此方法主要设置任务的执行状态,并判断是否要中断持有该任务线程的执行
public boolean cancel(boolean mayInterruptIfRunning) {
// 新建任务并且成功设置线程状态为中断中或取消状态
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // 设置了可能中断执行中的标志,则对持有该任务的线程设置中断标志位
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally {
// 设置中断标志位后直接将任务的状态设置为中断完成
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
get 方法主要获取当前任务的执行结果,有两种,一种无限期阻塞,另一种阻塞一定时间。
public V get() throws InterruptedException, ExecutionException {
int s = state;
// 判断当前状态是否未完成
if (s <= COMPLETING)
// 等待当前任务完成
s = awaitDone(false, 0L);
// 返回任务执行结果
return report(s);
}
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null)
throw new NullPointerException();
int s = state;
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
}
FutureTask类提供对应的钩子函数,由子类具体实现
protected void done() { }
设置任务的执行结果
protected void set(V v) {
// 通过乐观锁的方式设置当前线程的执行状态由新建变为完成中
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
// 设置执行结果
outcome = v;
// 设置状态为完成状态
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
// 通知唤醒阻塞线程
finishCompletion();
}
}
设置执行异常信息
protected void setException(Throwable t) {
// 设置状态为正在执行
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
// 设置异常信息
outcome = t;
// 设置任务状态为异常
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
线程执行任务时,调用的入口。
public void run() {
// 当前任务不是新建状态,或者设置执行任务的线程失败,直接返回
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
// 再次判断状态
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// 执行任务
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// 设置异常结果
setException(ex);
}
if (ran)
set(result);
}
} finally {
runner = null;
int s = state;
// 当前线程时中断中
if (s >= INTERRUPTING)
// 等待中断结束
handlePossibleCancellationInterrupt(s);
}
}
执行任务,除非任务失败,否则不设置任务状态为完成
protected boolean runAndReset() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {
Callable<V> c = callable;
if (c != null && s == NEW) {
try {
c.call(); // don't set result
ran = true;
} catch (Throwable ex) {
setException(ex);
}
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
return ran && s == NEW;
}
等待任务状态为中断完成
private void handlePossibleCancellationInterrupt(int s){
if (s == INTERRUPTING)
while (state == INTERRUPTING)
//让出cpu
Thread.yield();
}
static final class WaitNode {
// 阻塞线程
volatile Thread thread;
// 下一个阻塞节点
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); }
}
private void finishCompletion() {
// 获取等待节点列表,唤醒阻塞对接
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
// 设置当前节点为空,主要目的是帮助虚拟机回收垃圾
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
// 死循环
for (;;) {
// 获取被阻塞的线程
Thread t = q.thread;
if (t != null) {
// 帮助虚拟机回收对象
q.thread = null;
// 释放阻塞的线程
LockSupport.unpark(t);
}
// 执行下一个节点
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
done();
callable = null; // to reduce footprint
}
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
// 计算是否设置超时时间
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
// 线程设置了中断标志为则移除节点
if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
// 当前状态为完成
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
// 正在执行中状态
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
// 创建一个等待节点
else if (q == null)
q = new WaitNode();
else if (!queued)
// 将节点放入等待队列中
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
// 计算超时时间
nanos = deadline - System.nanoTime();
// 超过当前时间则返回并且移除节点
if (nanos <= 0L) {
removeWaiter(q);
return state;
}
// 等待设置的时间返回
LockSupport.parkNanos(this, nanos);
}
else
// 阻塞当前线程
LockSupport.park(this);
}
}
private volatile int state;
// 新建状态
private static final int NEW = 0;
// 完成中
private static final int COMPLETING = 1;
// 完成
private static final int NORMAL = 2;
// 异常
private static final int EXCEPTIONAL = 3;
// 取消
private static final int CANCELLED = 4;
// 中断中
private static final int INTERRUPTING = 5;
// 中断完成
private static final int INTERRUPTED = 6;
NEW -> COMPLETING -> NORMAL
NEW -> COMPLETING -> EXCEPTIONAL
NEW -> CANCELLED
NEW -> INTERRUPTING -> INTERRUPTED