FutureTask 源码

164 阅读3分钟

FutureTask代表了一个异步执行的任务。

public static void main(String[] args) throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(2);
    FutureTask task = new FutureTask(() -> 1);
    executorService.submit(task);
    System.out.println(task.get());
    //task.cancel(true);
    //task.isDone();

}

常用方法:

  • isDone 任务是否完成
  • get 无限期等待结果
  • cancel 取消任务

成员变量

//当前任务的状态
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;

/** The underlying callable; nulled out after running */
private Callable<V> callable;
//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;

run方法

//由于 FutureTask 实现了 RunnableFuture, RunnableFuture继承了Runnable,
//而线程池只执行Runnable的run方法,所以run方法是FutureTask放入线程,执行的第一个方法
public void run() {
    //状态必须是NEN新建状态,且成功的将其runner修改为当前线程,代表了FutureTask 就保留了当前正在执行他的线程,所以我们就可以通过runner对象,在cancel中中断线程
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        //执行体不为空,且当前状态为NEW状态,以最开始的示例为例,执行体为 () -> 1
        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的引用,help GC
        runner = null;
        // 判断状态是否被中断,如果中断,调用handlePossibleCancellationInterrupt处理中断
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

setException

//当任务执行时发生了异常,那么调用该方法,将FutureTask变为异常完成状态。
//转换的时候会有一个中间状态COMPLETING。在框架设计或者源码编写的时候,只要涉及到高并发,
//大部分做状态转换时,会出现中间状态。
protected void setException(Throwable t) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        //putOrderedInt不保证可见性,但是保证不会发生重排序,也即不会重排序到上一行代码中
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        finishCompletion();
    }
}

finishCompletion

//完成整个FutureTask的执行
private void finishCompletion() {
    // assert state > COMPLETING;
    for (WaitNode q; (q = waiters) != null;) {
        //如果有别的线程等待当前任务完成,将他们唤醒
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            for (;;) {
                Thread t = q.thread;
                //等待线程不为空,调用LockSupport.unpark唤醒
                if (t != null) {
                    q.thread = null;
                    LockSupport.unpark(t);
                }
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null; // 断开保留下一个任务的链 help gc
                q = next;
            }
            break;
        }
    }
    //此时所有等待任务完成的线程都被唤醒,回调子类的钩子函数
    done();

    callable = null;        // to reduce footprint
}

set

//调用该函数设置FutureTask正常完成,实现和 setException类似,只是设置的状态不一样
protected void set(V v) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = v;
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
        finishCompletion();
    }
}

cancel

//外部线程可以通过该方法的调用,取消任务的执行,mayInterruptIfRunning指明是否中断调用线程。
//此时,任务可能处于哪些状态:1、没有被执行 2、正在执行中 3、已经执行完成
public boolean cancel(boolean mayInterruptIfRunning) {
    //如果当前线程已经完成(可能正在完成中,可能已经完成),返回false
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    // 如果指定了中断线程,调用线程的interrupt()中断线程
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        //最终还是要调用完成任务的方法
        finishCompletion();
    }
    return true;
}