#概述 FutureTask类是可取消式异步计算方法。该类是Future接口的基本实现。能够开启和取消异步计算,查询异步计算结果是否完成,而且抽取出计算结果。计算结果只能在异步计算完成后被获取。异步计算一旦完成,计算将不能被从新开始和取消。除非计算过程的调用使用了runAndReset方法。 Callable和Runnable类都可以包装成FutureTask类。FutureTask自己实现了Runnable接口,并可以被提到Executor中去执行。 做为独立的类,其内部有protested方法用于执行任务。 #静态方法块java
try { //使用了unsafe设置state、runner和waiters的字段偏移量。 UNSAFE = sun.misc.Unsafe.getUnsafe(); Class<?> k = FutureTask.class; stateOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("state")); runnerOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("runner")); waitersOffset = UNSAFE.objectFieldOffset (k.getDeclaredField("waiters")); } catch (Exception e) { throw new Error(e); }
#任务运行状态 在FutureTask类中任务的运行状态设置为七种。 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; 任务运行状态之间的转换以下:app
NEW -> COMPLETING -> NORMAL NEW -> COMPLETING -> EXCEPTIONAL NEW -> CANCELLED NEW -> INTERRUPTING -> INTERRUPTED
#重要字段 //可执行任务 private Callable<V> callable; //异步计算结果或者get方法抛错信息 private Object outcome; // non-volatile, protected by state reads/writes //执行任务的线程 private volatile Thread runner; //等待线程队列 private volatile WaitNode waiters;异步
#重要方法 ##构造this
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
public FutureTask(Runnable runnable, V result) { //将runnable wrapper成callable this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable }
##任务取消线程
public boolean cancel(boolean mayInterruptIfRunning) { if (state != NEW) return false; if (mayInterruptIfRunning) { if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING)) return false; Thread t = runner; if (t != null) t.interrupt(); UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state } else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED)) return false; finishCompletion(); return true; }
取消任务方法接收了一个布尔类型的变量 一、若是变量为true,则首先尝试将运行状态设置为interrupting,若是不容许则返回false,标示取消失败。不然得到任务,作中断操做,将对象的状态字段置为INTERRUPTED。 二、若是变量为false或者未设置,则直接尝试将任务状态置为cancelled,若是失败则返回false,表示取消失败。不然执行finishCompletion(),将全部线程队列中等待的线程所有释放掉。等待gc回收。 ##执行(任务不能被打断)指针
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); } }
任务运行首先判断任务执行状态,若是当前任务执行状态不是new或者设置当前线程为执行线程操做失败,则返回空。 而后得到任务callable,若是任务状态是new而且任务非空,则调用call()方法得到结果,若是在异步计算的过程当中抛异常则将返回null的结果。 最后继续得到任务执行状态,若是任务处于INTERRUPTING状态,则处理中断。code
##任务执行(容许reset)orm
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; }
和前一个run方法不一样的有两个地方。第一个就是增长了一个boolean变量ran,第二个就是没有设置result。 ##得到结果对象
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); }
得到结果的方法首先判断时间单位,若是未设置会抛空指针。而后得到任务运行状态,若是状态是未完成,而且等待指定时间后让然没有得到结果,则跑超时异常,不然运行 report(s)。接口
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); }
report(s)方法会判断任务执行状态,根据状态是normal仍是cancelled分别返回执行结果或异常信息。