future异步回调的实现:
本地持有线程池调度的callable和运行的thread的引用,内部持有任务执行状态和任务获取的观察者
future内部持有的状态如下说明
/**
* The run state of this task, initially NEW. The run state
* transitions to a terminal state only in methods set,
* setException, and cancel. During completion, state may take on
* transient values of COMPLETING (while outcome is being set) or
* INTERRUPTING (only while interrupting the runner to satisfy a
* cancel(true)). Transitions from these intermediate to final
* states use cheaper ordered/lazy writes because values are unique
* and cannot be further modified.
*
* Possible state transitions:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
private volatile int state;
//对应任务未执行或者执行中
private static final int NEW = 0;
//在run方法Callable完成的时候,调用set(V v)/setException(Throwable t)进行值回写前设置,
//代表任务执行完毕正在回写阶段(回写的数据是处理结果或者处理过程中的异常)
private static final int COMPLETING = 1;
//在run方法Callable完成的时候,调用set(V v)进行值回写完成后设置,代表任务执行完毕
private static final int NORMAL = 2;
//在run方法Callable抛出异常的时候,调用setException(Throwable t)进行值回写完成后设置,
//代表任务执行完毕异常回写完毕
private static final int EXCEPTIONAL = 3;
//在cancel(boolean mayInterruptIfRunning)中,当任务状态是new的时候,mayInterruptIfRunning=false
//修改任务状态,不会中断在执行的thread,但是不会在获取任务执行完毕后的结果
private static final int CANCELLED = 4;
//在cancel(boolean mayInterruptIfRunning)中,当任务状态是new的时候,mayInterruptIfRunning=true
//修改任务状态,进行中断在执行的thread前设置
private static final int INTERRUPTING = 5;
//在cancel(boolean mayInterruptIfRunning)中,当任务状态是new的时候,mayInterruptIfRunning=true
//修改任务状态,中断在执行的thread后设置,不会在获取任务执行完毕后的结果
private static final int INTERRUPTED = 6;
future实现异步回调的核心我认为是 它持有了执行任务的线程的引用和处理结果的引用
通过对处理进度的监控进行内部状态流转进而来协调get和cancel操作
/** The underlying callable; nulled out after running */
private Callable<V> callable;
/** The result to return or exception to throw from get() */
private Object outcome; // non-volatile, protected by state reads/writes
/** The thread running the callable; CASed during run() */
private volatile Thread runner;
/** Treiber stack of waiting threads */
private volatile WaitNode waiters;
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 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
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}