FutureTask分析

(一)关键概念点

1、Future简介

Future是一个带泛型的接口类,主要定义了五个方法,大致分为三个作用:取消线程执行、线程是否取消或完成和获得返回值。

public interface Future<V> {
    //取消线程或中断线程
    boolean cancel(boolean mayInterruptIfRunning);
    //是否被中断
    boolean isCancelled();
    //是否完成
    boolean isDone();
    //获得返回值
    V get() throws InterruptedException, ExecutionException;
    //超时获取返回值
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

2、Callable简介

Callable也是一个带泛型的接口类,其中仅定义了一个带有返回值的call方法,主要是提供返回值。

public interface Callable<V> {
    //主要是得到线程执行完后的返回值
     V call() throws Exception;
 }

3、FutureTask简介

FutureTask是一个实现RunnableFuture接口的实现类,其中RunnableFuture是继承于Future和Runnable接口; 一般线程执行都是使用继承Thread或实现Runnable接口中的抽象方法run,但是这种都是void类型,是没有返回值, 故如果执行线程后需要得到返回值时,FutureTask随之诞生,同时也是在使用线程池ThreadPoolExecutor的submit时更符合Runnable或Callable这类型的参数。

FutureTask实际上是适配器设计模式的体现,在类级别上直接实现RunnableFuture,间接上实现Runnable和Future接口,其内部更是使用Callable变量——callable,在构造方法中对其初始化,自身内部实现的run方法中进行调用callable中的call方法。
在这里插入图片描述

(二)FutureTask生命周期

1、FutureTask生命状态值

FutureTask生命周期主要是依靠state变量的值来实现转换。

   private volatile int state;//定义state变量,初始值会被设置为New
   private static final int NEW          = 0;//初始状态(代表callable被赋值,也是线程执行完成run之前的状态)
   private static final int COMPLETING   = 1;//线程任务执行完毕时的状态
   private static final int NORMAL       = 2;//线程执行完任务将结果更新后的状态
   private static final int EXCEPTIONAL  = 3;//线程执行过程发生异常后的状态
   private static final int CANCELLED    = 4;//线程未被执行前就被取消(cancel方法)后的状态
   private static final int INTERRUPTING = 5;//线程正在运行时被设置被中断后的状态
   private static final int INTERRUPTED  = 6;//线程中断完毕后的状态

2、FutureTask生命状态变化

state初始化为NEW,仅在set方法,setException方法和cancel方法中state才可以转变为终态,在任务完成前,state的值可能为COMPLETING或INTERRUPTING。
state有四种可能的状态转换:

(1)线程正常执行完毕:NEW -> COMPLETING -> NORMAL
(2)线程执行过程中发生异常:NEW -> COMPLETING -> EXCEPTIONAL
(3)线程初始化后未执行前就执行了cancel方法:NEW -> CANCELLED
(4)线程执行过程中被中断:NEW -> INTERRUPTING -> INTERRUPTED

3、其他辅助变量

  /**
   * The underlying callable; nulled out after running
   * run运行时会调用其方法call(),并得到结果,任务结束够会被置为null
   */
   private Callable<V> callable;
   /**
    * The result to return or exception to throw from get()
    * 计算结果的存储变量,使用get获取值实际上获取该值(异常后是异常值)
    * non-volatile, protected by state reads/writes
    */
   private Object outcome;

   /**
    * The thread running the callable; CASed during run()
    * worker thread 执行线程
    */
   private volatile Thread runner;
   /**
    * Treiber stack of waiting threads
    * 并发stack数据结构,FutureTask在任务执行前被多次get方法阻塞的线程。
    */
   private volatile WaitNode waiters;

(三)FutureTask源码分析

1、构造方法

 /**
   * 接收一个Callable类型的参数对内部callable变量直接赋值
   * state值初始化为New状态
   */
  public FutureTask(Callable<V> callable) {
      if (callable == null)
          throw new NullPointerException();
      this.callable = callable;
      this.state = NEW;       // ensure visibility of callable
  }
  /**
   * 用Runnable参数和返回类型来构造callable变量,内部使用Executors中callable进行构造
   * state值初始化为New状态
   */
  public FutureTask(Runnable runnable, V result) {
      this.callable = Executors.callable(runnable, result);//静态方法初始化,内含适配器模式
      this.state = NEW;       // ensure visibility of callable
  }

Executors工具类:

  public static <T> Callable<T> callable(Runnable task, T result) {
      if (task == null)
          throw new NullPointerException();
      return new RunnableAdapter<T>(task, result);//适配器构造
  }

Executors工具类中的内部类:

//适配器类
  static final class RunnableAdapter<T> implements Callable<T> {
      final Runnable task;
      final T result;
      RunnableAdapter(Runnable task, T result) {//适配器模式构造
          this.task = task;
          this.result = result;
      }
      public T call() {//实现Callable接口类中的接口
          task.run();//统一调用FutureTask中的run方法
          return result;
      }
  }

2、run方法(核心)

线程创建完毕后,第一种是将其提交给线程池来执行,第二种也可以自行使用start开启,无论那种方法最终都会执行FutureTask中的run方法,前者是call方法中使用task.run方法,后者更是重写run方法, FutureTask中的run方法内部都会调用Callable中call方法(该线程是使用Callable创建)。

/**
 * 线程执行统一入口,无论Callable方式创建的线程或Thread或Runnable方式创建的,均由该处执行
 * 保证线程只允许被执行一次且将结果缓存到outcome变量
 */
public void run() {
    /**
     * 判断线程是否被重复启用,只允许运行一次,条件如下:
     * 条件一:线程状态不为初始状态,被执行者改变过状态
     * 条件二:线程的执行者不为空,代表已有执行者
     */
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this,runnerOffset,null,Thread.currentThread()))
        return;
    /**
     * 内部调用Callable中的call方法
     * 执行call方法抛异常的处理方法setException
     * 正常执行完毕状态更改方法set
     */
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {//满足正常执行条件
            V result;
            boolean ran;
            try {
                result = c.call();//适配器模式后的调用call方法
                ran = true;//在正常得到返回值的前提下,保证能执行set方法
            } catch (Throwable ex) {
                result = null;
                ran = false;
                setException(ex);//异常时执行的方法
            }
            if (ran)//正常执行完线程call后的条件
                set(result);//将结果缓存到outcome中
        }
    } finally {
        runner = null;//执行者置空
        // 线程是否被中断,如果被中断则需要改变状态
        int s = state;
        if (s >= INTERRUPTING)
            handlePossibleCancellationInterrupt(s);
    }
}

3、set方法

/**
 * 在run中得到返回值后需要将结果缓存和唤醒阻塞线程
 * set是改变state状态前后将结果缓存到outcome变量
 * finishCompletion是唤醒阻塞线程
 */
protected void set(V v) {
    //任务即将结束前的状态,CAS保证原子性,state是volatile类型
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = v;//将值赋值即缓存
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); //线程state的最终变量即正常结束的最后状态
        finishCompletion();//
    }
}
//唤醒阻塞线程
private void finishCompletion() {
   // assert state > COMPLETING;
   for (WaitNode q; (q = waiters) != null;) {//遍历等待者
       if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {//cas将阻塞线程变量置空
           for (;;) {//自旋唤醒所有阻塞线程
               Thread t = q.thread;
               if (t != null) {
                   q.thread = null;
                   LockSupport.unpark(t);//唤醒线程,LockSupport请查看其他文章
               }
               WaitNode next = q.next;//后继节点
               if (next == null)//直到所有线程唤醒完毕跳出循环
                   break;
               q.next = null; // unlink to help gc
               q = next;//重新赋值WaitNode
           }
           break;
       }
   }
  done();//子类重写时自定义重写,默认为空实现
  callable = null;//help GC
}

4、get方法(核心)

/**
 * 获取返回值
 * 如果run中的call方法未执行完则会阻塞awaitDone,反之则返回值report
 */
public V get() throws InterruptedException, ExecutionException {
    int s = state;
    if (s <= COMPLETING)//判断线程任务是否完成,利用state值判定
        s = awaitDone(false, 0L);//进行阻塞
    return report(s);//返回值
}
/**
 * awaitDone阻塞方法,参数timed和nanos主要是兼容超时阻塞和非超时阻塞
 */
private int awaitDone(boolean timed, long nanos)
    throws InterruptedException {
    final long deadline = timed ? System.nanoTime() + nanos : 0L;//超时时间
    WaitNode q = null;
    boolean queued = false;
    for (;;) {
        if (Thread.interrupted()) {//判断是否有中断标志
            removeWaiter(q);//移除等待者(多个WaitNode时,内部是循环置空)
            throw new InterruptedException();
        }
        int s = state;
        if (s > COMPLETING) {//for自旋时判断task状态是否大于1,若是则代表其他线程已经将任务执行完毕
            if (q != null)
                q.thread = null;
            return s;
        }
        else if (s == COMPLETING) //如果state为1,则代表其他线程正处在更新结果值,释放资源
            Thread.yield();//释放线程资源
        else if (q == null)//此时代表需要进行阻塞
            q = new WaitNode();//创建等待者节点WaitNode
        else if (!queued)//默认为false,会进行入队
            queued = UNSAFE.compareAndSwapObject(this, waitersOffset,q.next = waiters, q);
        else if (timed) {//是否进行超时阻塞
            nanos = deadline - System.nanoTime();
            if (nanos <= 0L) {//超时控制
                removeWaiter(q);
                return state;
            }
            LockSupport.parkNanos(this, nanos);//超时阻塞
        }
        else
            LockSupport.park(this);//直接阻塞
    }
}

/**
 * 返回缓存值,基于state值即s
 */
private V report(int s) throws ExecutionException {
    Object x = outcome;//内部核心变量缓存值outcome
    if (s == NORMAL)//正常结束状态则返回
        return (V)x;
    if (s >= CANCELLED)//task状态大于等于3,代表状态异常
        throw new CancellationException();
    throw new ExecutionException((Throwable)x);
}

5、辅助方法(Future接口中的方法)

 /**
  * 通过state值与取消状态对比
  */
 public boolean isCancelled() {
     return state >= CANCELLED;
 }
 /**
  * 通过state值与初始状态对比,不是NEW状态则代表完成,正常执行情况大部分为New状态,正在更新值状态可默认为完成
  */
 public boolean isDone() {
     return state != NEW;
 }
  /**
   * 取消任务执行情况,包含未执行和正在执行两部分
   * 传递一个布尔值对其任务更改,未执行状态则无论false还是true都返回true,
   * 不同的是false是设置取消状态,true是设置为中断状态
   * 传递一个布尔值对其任务更改,正在执行状态中传递true时会对其state状态更改未取消状态,
   */
 public boolean cancel(boolean mayInterruptIfRunning) {
     /**
      * 此处会判断state值的改变情况:
      * 第一种:task任务还没开始执行,会根据mayInterruptIfRunning进行中断还是取消状态改变
      * 第二种:task任务执行完毕(标志为state不是NEW状态),则直接返回false
      * 第三种:task在NEW的前提下,CAS失败时说明state在某一时刻改变,则表明任务发生其他变化,返回false,取消失败
      */
     if (!(state == NEW &&
           UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
               mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
         return false;
     try {
         if (mayInterruptIfRunning) {
             try {
                 Thread t = runner;
                 if (t != null)
                     t.interrupt();
             } finally { // final state
                 UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
             }
         }
     } finally {
         finishCompletion();//唤醒阻塞线程
     }
     return true;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值