【JUC源码解析】FutureTask
简介
FutureTask, 一个支持取消行为的异步任务执行器。
概述
FutureTask实现了Future,提供了start, cancel, query等功能,并且实现了Runnable接口,可以提交给线程执行。
源码分析
状态
1 private volatile int state; // 执行器状态 2 private static final int NEW = 0; // 初始值 3 private static final int COMPLETING = 1; // 完成进行时 4 private static final int NORMAL = 2; // 正常结束 5 private static final int EXCEPTIONAL = 3; // 发生异常 6 private static final int CANCELLED = 4; // 已经取消 7 private static final int INTERRUPTING = 5; // 中断进行时 8 private static final int INTERRUPTED = 6; // 中断结束
转换
NEW -> COMPLETING -> NORMAL
NEW -> COMPLETING -> EXCEPTIONAL
NEW -> CANCELLED
NEW -> INTERRUPTING -> INTERRUPTED
属性
1 private Callable<V> callable; // 任务 2 private Object outcome; // 返回结果 3 private volatile Thread runner; // 执行线程 4 private volatile WaitNode waiters; // 等待线程们
run()
1 public void run() { 2 // UNSAFE.compareAndSwapObject, CAS保证Callable任务只被执行一次 3 if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) 4 return; 5 try { 6 Callable<V> c = callable; // 拿到执行任务 7 if (c != null && state == NEW) { // 任务不为空,并且执行器状态是初始值,才会执行;如果取消就不执行了 8 V result; 9 boolean ran; // 记录是否执行成功 10 try { 11 result = c.call(); // 执行任务 12 ran = true; // 成功 13 } catch (Throwable ex) { 14 result = null; // 异常,清空结果 15 ran = false; // 失败 16 setException(ex); // 记录异常 17 } 18 if (ran) // 问题:ran变量可以省略吗,把set(result);移到try块里面? 19 set(result); // 设置结果 20 } 21 } finally { 22 runner = null; // 直到set状态前,runner一直都是非空的,为了防止并发调用run()方法。 23 int s = state; 24 if (s >= INTERRUPTING) // 有别的线程要中断当前线程,把CPU让出去,自旋等一下 25 handlePossibleCancellationInterrupt(s); 26 } 27 }
- 检查state,非NEW,说明已经启动,直接返回;否则,设置runner为当前线程,成功则继续,否则,返回。
- 调用Callable.call()方法执行任务,成功则调用set(result)方法,失败则调用setException(ex)方法,最终都会设置state,并调用finishCompletion()方法,唤醒阻塞在get()方法上的线程们。
- 接2,如注释所示,如果省略ran变量,并把"set(result);" 语句移动到try代码块"ran = true;" 语句处,会怎样呢?首先,从代码逻辑上看,是没有问题的,但是,考虑到"set(result);"方法万一抛出异常甚至是错误了呢?set()方法最终会调用到用户自定义的done()方法,所以,不可省略。
- 如果state为INTERRUPTING, 则主动让出CPU,自旋等待别的线程执行完中断流程。见handlePossibleCancellationInterrupt(int s) 方法。
set(V)
1 protected void set(V v) { 2 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { // CAS state NEW -> COMPLETING 3 outcome = v; // 将结果赋值给outcome 4 UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // 然后将state修改为NORMAL,表示现在可以获取返回结果 5 finishCompletion(); // 唤醒等待的所有线程 6 } 7 }
setException(Throwable)
1 protected void setException(Throwable t) { 2 if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { // CAS state NEW -> COMPLETING 3 outcome = t; // 将结果赋值给outcome 4 UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // 然后将state修改为EXCEPTIONAL,表示现在可以获取返回异常信息 5 finishCompletion(); // 唤醒等待的所有线程 6 } 7 }
handlePossibleCancellationInterrupt(int)
1 private void handlePossibleCancellationInterrupt(int s) { 2 if (s == INTERRUPTING) // 当state为INTERRUPTING时 3 while (state == INTERRUPTING) // 表示有线程正在中断当前线程 4 Thread.yield(); // 让出CPU,自旋等待中断 5 }
finishCompletion()
1 private void finishCompletion() { 2 for (WaitNode q; (q = waiters) != null;) { 3 if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { // CAS waiters -> null,避免重复 4 for (;;) { 5 Thread t = q.thread; // 获得结点对应的线程 6 if (t != null) { // 如果不为空 7 q.thread = null; // 复位thread属性 8 LockSupport.unpark(t); // 唤醒此线程 9 } 10 WaitNode next = q.next; // 取得下一个结点 11 if (next == null) // 如果为空则跳出内层循环,继而跳出外层循环 12 break; 13 q.next = null; // 复位next属性 14 q = next; // 移动到下一个结点 15 } 16 break; // 跳出外层循环 17 } 18 // 如果CAS失败,说明waiters发生变化,则重试,直至CAS成功,或者waiters为null(别的线程已经完成此操作) 19 } 20 21 done(); // 调用done()方法,hook钩子,子类实现 22 23 callable = null; // 复位callable,其所表示的任务已结束 24 }
将结点一个一个地弹出,并唤醒其所持的线程。
WaitNode
1 static final class WaitNode { 2 volatile Thread thread; // 线程 3 volatile WaitNode next; // 指向下一个结点 4 5 WaitNode() { 6 thread = Thread.currentThread(); // 当前线程 7 } 8 }
runAndReset()
1 protected boolean runAndReset() { 2 // UNSAFE.compareAndSwapObject, CAS保证Callable任务只被执行一次 3 if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) 4 return false; 5 boolean ran = false; // 记录是否执行成功 6 int s = state; // 状态 7 try { 8 Callable<V> c = callable; // 任务 9 if (c != null && s == NEW) { // 任务不为空,并且执行器状态是初始值,才会执行;如果取消就不执行了 10 try { 11 c.call(); // 不设置结果,可重复执行 12 ran = true; 13 } catch (Throwable ex) { 14 setException(ex); // 直至遇到异常 15 } 16 } 17 } finally { 18 runner = null; // 置空,其他线程可以继续执行 19 s = state; // 状态 20 if (s >= INTERRUPTING) // 有别的线程要中断当前线程,把CPU让出去,自旋等一下 21 handlePossibleCancellationInterrupt(s); 22 } 23 return ran && s == NEW; // 返回结果,执行成功,并且,state为NEW,才返回true 24 }
get()
1 public V get() throws InterruptedException, ExecutionException { 2 int s = state; // 执行器状态 3 if (s <= COMPLETING) // 如果状态小于等于COMPLETING,说明任务正在执行,需要等待 4 s = awaitDone(false, 0L); // 等待 5 return report(s); // 报告结果 6 }
get(long, TimeUnit)
1 public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { 2 if (unit == null) // 参数校验 3 throw new NullPointerException(); 4 int s = state; // 执行器状态 5 if (s <= COMPLETING && (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING) // 如果状态小于等于COMPLETING,说明任务正在执行,需要等待;等待指定时间,state依然小于等于COMPLETING 6 throw new TimeoutException(); // 抛出超时异常 7 return report(s); // 报告结果 8 }
report(int)
1 private V report(int s) throws ExecutionException { 2 Object x = outcome; // 返回结果 3 if (s == NORMAL) // 如果state为NORMAL,表示任务正常结束,返回结果 4 return (V) x; 5 if (s >= CANCELLED) // 如果任务大于等于CANCELLED,表示任务已经取消,抛出取消异常 6 throw new CancellationException(); 7 throw new ExecutionException((Throwable) x); // 否则,抛出执行异常 8 }
awaitDone(boolean timed, long nanos)
1 private int awaitDone(boolean timed, long nanos) throws InterruptedException { 2 final long deadline = timed ? System.nanoTime() + nanos : 0L; // 计算deadline 3 WaitNode q = null; // 等待结点 4 boolean queued = false; // 是否已经入队 5 for (;;) { 6 if (Thread.interrupted()) { // 如果当前线程已经标记中断,则直接移除此结点,并抛出中断异常 7 removeWaiter(q); 8 throw new InterruptedException(); 9 } 10 11 int s = state; // 执行器状态 12 if (s > COMPLETING) { // 如果状态大于COMPLETING,说明任务已经完成,或者已经取消,直接返回 13 if (q != null) 14 q.thread = null; // 复位线程属性 15 return s; // 返回 16 } else if (s == COMPLETING) // 如果状态等于COMPLETING,说明正在整理结果,自旋等待一会儿 17 Thread.yield(); 18 else if (q == null) // 初始,构建结点 19 q = new WaitNode(); 20 else if (!queued) // 还没入队,则CAS入队 21 queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); 22 else if (timed) { // 是否允许超时 23 nanos = deadline - System.nanoTime(); // 计算等待时间 24 if (nanos <= 0L) { // 超时 25 removeWaiter(q); // 移除结点 26 return state; // 返回结果 27 } 28 LockSupport.parkNanos(this, nanos); // 线程阻塞指定时间 29 } else 30 LockSupport.park(this); // 阻塞线程 31 } 32 }
removeWaiter(WaitNode)
1 private void removeWaiter(WaitNode node) { 2 if (node != null) { // 移除结点的标准是thread属性已经为null 3 node.thread = null; // 每个线程对应一个结点,当需要移除时,仅仅需要将thread属性置为null即可,此过程可并发执行 4 retry: for (;;) { // 然而,移除操作需要穿行协作,一有变动,须重试 5 for (WaitNode pred = null, q = waiters, s; q != null; q = s) { // 记录前驱结点,当前结点,以及后继结点 6 s = q.next; // 后继结点 7 if (q.thread != null) // 不为null, 前驱指向当前结点,即整体右移,左边的结点是安全的。表示不必删除 8 pred = q; 9 else if (pred != null) { // 如果当前线程为空,前驱不为null 10 pred.next = s; // 前驱越过当前结点指向后继结点,等于把当前结点移除了 11 if (pred.thread == null) // 如果前驱结点thread属性也为null,则很可能任务完成,线程unpark了,需要从头检查一下。 12 continue retry; 13 } else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s)) // CAS失败,waiters变动,重试 14 continue retry; 15 } 16 break; // 跳出 17 } 18 } 19 }
cancel(boolean)
1 public boolean cancel(boolean mayInterruptIfRunning) { 2 // 状态不为NEW,或者CAS NEW -> INTERRUPTING/CANCELLED, 直接返回 3 if (!(state == NEW 4 && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) 5 return false; 6 try { 7 if (mayInterruptIfRunning) { // 中断 8 try { 9 Thread t = runner; 10 if (t != null) 11 t.interrupt(); // 中断此线程 12 } finally { 13 UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // state设置为INTERRUPTED 14 } 15 } 16 } finally { 17 finishCompletion(); // 唤醒阻塞线程 18 } 19 return true; 20 }
至此,结束。
尊重他人的劳动,转载请注明出处:http://www.cnblogs.com/aniao/p/aniao_futuretask.html