在学习多线程的时候,了解了FutureTask
FutureTask 表示一个异步运算的任务。FutureTask 里面可以传入一个 Callable 的具体实现类,可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。
里面的基本字段介绍
// 表示当前task状态
private volatile int state;
// 当前任务尚未执行
private static final int NEW = 0;
// 当前任务正在结束 , 稍微完全结束,一种临界状态
private static final int COMPLETING = 1;
// 当前任务正常结束
private static final int NORMAL = 2;
// 当前任务执行过程中发生了异常,内部封装的 callable.run()向上抛出异常了
private static final int EXCEPTIONAL = 3;
// 当前任务被取消
private static final int CANCELLED = 4;
// 当前任务中段中
private static final int INTERRUPTING = 5;
// 当前任务已中断
private static final int INTERRUPTED = 6;
// submit(runnable/callable) 使用装饰者模式 伪装 成 Callable接口
private Callable<V> callable;
/** The result to return or exception to throw from get() */
// 正常情况: 任务正常执行结束, 保存执行结果。 callable返回值
// 非正常情况: 向上抛出异常,outCome保存异常
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 */
// 因为会有很多线程去get当前任务的结果,所以这里会使用一种数据结果 stack 头插 头取队列
private volatile WaitNode waiters;
FutureTask的构造函数
public FutureTask(Runnable runnable, V result) {
// 使用装饰者模式将Runnable转换为了 callable接口,外部线程通过 get获取
// 当前任务执行结果时,结果可能为 null 有可能为传进来的值
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
里面的run方法
public void run() {
// 条件一: state != NEW 成立,说明当前task已经被执行了,或者被cancel了。
// 条件二: cas 失败,说明当前任务已经被其他线程抢占了
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
// 执行到这里,当前task 一定是 New状态,而且当前线程也抢占task成功
try {
// callable 就是自己封装逻辑的 callable 或者 装饰后的 runnable
Callable<V> c = callable;
//条件一: 防止 空指针
// 条件二: state == New 再次判断,防止外部线程 cancel当前任务
if (c != null && state == NEW) {
// 结果引用
V result;
// true 表示 callable.run 代码块执行成功,未抛出异常
// false: 抛出异常
boolean ran;
try {
// 调用自己实现的 callable 或者装饰后的 runnable
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);
}
}