FutureTask源码解析

276 阅读3分钟

实现

  • FutureTask实现了Runnable接口,所以它可以放到线程池中去执行
  • FutureTask实现了Future接口,所以它具有cancel任务的能力

状态

  • NEW = 0 : 初始状态
  • COMPLETING = 1 :正在设置任务结果(中间状态)
  • NORMAL = 2 :任务正常执行完毕(结束状态)
  • EXCEPTIONAL = 3 :任务执行过程中发生异常(结束状态)
  • CANCELLED = 4 :任务被取消(结束状态)
  • INTERRUPTING = 5 :正在中断运行任务的线程(中间状态)
  • INTERRUPTED = 6 :任务被中断(结束状态)

状态的转化:

  • NEW -> COMPLETING -> NORMAL
  • NEW -> COMPLETING -> EXCEPTIONAL
  • NEW -> CANCELLED
  • NEW -> INTERRUPTING -> INTERRUPTED

==任务的中间状态只是一个瞬态,非常短暂,而且任务的中间态并不代表任务正在执行,而是任务已经执行完了,正在设置最终的返回结果,所以只要state不处于 NEW 状态,就说明任务已经执行完毕==

属性

  • outcome:返回值或者get()方法抛出的异常
  • waiters:等待任务完成的线程链表(单向)
  • callable:要执行的任务

构造器

参数支持Callable和Runnable(Runnable构造成Callable),赋值给callable,state值为NEW

方法

  • run
public void run() {
    //state是NEW时,cas去设置为当前线程
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                     null, Thread.currentThread()))
        return;
    try {
        Callable<V> c = callable;
        //任务不为null,且状态是初始状态才执行任务
        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 = null;
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}
  • set
//设置结果到outcome,更新state值
protected void set(V v) {
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = v;
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
        finishCompletion();
    }
}
  • get
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    /**
     * 如果任务还没有完成,就会一直阻塞直至任务完成
     * 它的重载方法get(long timeout, TimeUnit unit)可以指定等待时间
     */
    if (s <= COMPLETING)
        s = awaitDone(false, 0L);
    return report(s);
}

/**
 * 如果执行正常完成,返回结果值outcome(在set方法中设置的值)
 * 任务被取消的话,抛出CancellationException
 * 任务执行中抛出异常的话,get方法抛出ExecutionException(不管执行中抛出什么异常)
 */
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);
}
  • cancel
  1. 如果任务还没开始,此时调用cancel,任务被取消,返回true
  2. 任务已经完成或者被取消,此时调用cancel,取消失败(没有可取消的了),返回false
  3. 任务正在执行中,如果mayInterruptIfRunning=true,执行任务的线程会收到一个中断信号,做一些中断处理;如果mayInterruptIfRunning=false,不中断正在执行的任务,返回false
public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    // in case call to interrupt throws exception
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

那么如何来判断如果mayInterruptIfRunning是true还是false呢

  • true适合用于明确知道任务是可以响应中断信号的
  • false适合用于不清楚任务能不能响应中断信号以及希望任务一旦开始就执行完成

Demo

public void test() throws InterruptedException, TimeoutException, ExecutionException {
    FutureTask<String> futureTask = new FutureTask<>(()->{
        Thread.sleep(3000);
        return "hello world";
    });

    ExecutorService es = Executors.newFixedThreadPool(1);
    es.submit(futureTask);
    System.out.println(futureTask.get(4, TimeUnit.SECONDS));
}