SoFunction
Updated on 2025-03-11

Futuretask source code analysis (recommended)

FutureTask only implements the RunnableFuture interface:

This interface inherits the characteristics of the future interface, that is, inherits the characteristics of these two interfaces.

1. You don’t have to directly inherit Thread to generate subclasses. As long as you implement the run method and pass the instance into the Thread constructor, Thread can execute the run method of the instance (Thread(Runnable)).

2. The task can be executed independently. When getting the task execution results, it can be blocked until the execution results are completed. Execution can also be interrupted, execution status can be judged, etc.

FutureTask is an asynchronous task executor that supports cancel behavior. This class implements the method of the Future interface.

For example: 1. Cancel task execution

2. Query whether the task is completed

3. Get the task execution result (the "get" task must be executed to obtain the result, otherwise it will block until the task is completed).

Note: Once the task execution is completed, cancel the task or restart the task cannot be performed. (Unless you use runAndReset mode to run the task from the beginning)
FutureTask supports the implementation classes of two tasks, Callable or Runnable. And the FutureTask instance can be handed over to the Executor to execute.

Source code part (very simple):

public class FutureTask<V> implements RunnableFuture<V> {
  /*
   * Revision notes: This differs from previous versions of this
   * class that relied on AbstractQueuedSynchronizer, mainly to
   * avoid surprising users about retaining interrupt status during
   * cancellation races. Sync control in the current design relies
   * on a "state" field updated via CAS to track completion, along
   * with a simple Treiber stack to hold waiting threads.
   *
   * Style note: As usual, we bypass overhead of using
   * AtomicXFieldUpdaters and instead directly use Unsafe intrinsics.
   */
  /**
   * The run state of this task, initially NEW. The run state
   * transitions to a terminal state only in methods set,
   * setException, and cancel. During completion, state may take on
   * transient values of COMPLETING (while outcome is being set) or
   * INTERRUPTING (only while interrupting the runner to satisfy a
   * cancel(true)). Transitions from these intermediate to final
   * states use cheaper ordered/lazy writes because values are unique
   * and cannot be further modified.
   *
   * Possible state transitions:
   * NEW -> COMPLETING -> NORMAL
   * NEW -> COMPLETING -> EXCEPTIONAL
   * NEW -> CANCELLED
   * NEW -> INTERRUPTING -> INTERRUPTED
   */
  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;
  /** is used to store task execution results or exception objects. According to the task state, choose to return the execution results or throw an exception when getting */
  private Object outcome; // non-volatile, protected by state reads/writes
  /** The thread currently running the Run method */
  private volatile Thread runner;
  /** Treiber stack of waiting threads */
  private volatile WaitNode waiters;
  /**
   * Returns result or throws exception for completed task.
   *
   * @param s completed state value
   */
  @SuppressWarnings("unchecked")
  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);
  }
  /**
   * Creates a {@code FutureTask} that will, upon running, execute the
   * given {@code Callable}.
   *
   * @param callable the callable task
   * @throws NullPointerException if the callable is null
   */
  public FutureTask(Callable<V> callable) {
    if (callable == null)
      throw new NullPointerException();
     = callable;
     = NEW;    // ensure visibility of callable
  }
  /**
   * Creates a {@code FutureTask} that will, upon running, execute the
   * given {@code Runnable}, and arrange that {@code get} will return the
   * given result on successful completion.
   *
   * @param runnable the runnable task
   * @param result the result to return on successful completion. If
   * you don't need a particular result, consider using
   * constructions of the form:
   * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
   * @throws NullPointerException if the runnable is null
   */
  public FutureTask(Runnable runnable, V result) {
     = (runnable, result);
     = NEW;    // ensure visibility of callable
  }
  //Judge whether the task has been cancelled (exception interrupt, cancellation, etc.)  public boolean isCancelled() {
    return state >= CANCELLED;
  }
  /**
   Determine whether the task has ended (cancel, exception, completion, and NORMAL are all equal to end)
   **
   public boolean isDone() {
     return state != NEW;
   }
   /**
   mayInterruptIfRunning is used to determine the status of the task.
           true: Task status = INTERRUPTING = 5.  If the task is already running, it is forced to interrupt.  If the task is not running, it will not run again
           false: CANCELLED = 4.  If the task is already running, the run is allowed to complete (but the result cannot be obtained through get).  If the task is not running, it will not run again
   **/
  public boolean cancel(boolean mayInterruptIfRunning) {
    if (state != NEW)
      return false;
    if (mayInterruptIfRunning) {
      if (!(this, stateOffset, NEW, INTERRUPTING))
        return false;
      Thread t = runner;
      if (t != null)
        ();
      (this, stateOffset, INTERRUPTED); // final state
    }
    else if (!(this, stateOffset, NEW, CANCELLED))
      return false;
    finishCompletion();
    return true;
  }
  /**
   * @throws CancellationException {@inheritDoc}
   */
  public V get() throws InterruptedException, ExecutionException {
    int s = state;
    //If the task is not completed completely, then block until the thread is awakened after the task is completed    if (s <= COMPLETING)
      s = awaitDone(false, 0L);
    return report(s);
  }
  /**
   * @throws CancellationException {@inheritDoc}
   */
  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, (timeout))) <= COMPLETING)
      throw new TimeoutException();
    return report(s);
  }
  /**
   * Protected method invoked when this task transitions to state
   * {@code isDone} (whether normally or via cancellation). The
   * default implementation does nothing. Subclasses may override
   * this method to invoke completion callbacks or perform
   * bookkeeping. Note that you can query status inside the
   * implementation of this method to determine whether this task
   * has been cancelled.
   */
  protected void done() { }
  /**
   In FutureTask, only the run method is called after the task is completed.
   Mainly saves the task execution results into the member variable outcome and switches the task execution status.
   From this method we can know:
   COMPLETING: The task has been executed (or may be completed abnormally), but the result has not been set to the member variable outcome, which also means that it cannot get it yet.
   NORMAL: Complete task execution
   **/
  protected void set(V v) {
    if ((this, stateOffset, NEW, COMPLETING)) {
      outcome = v;
      (this, stateOffset, NORMAL); // final state
      finishCompletion();
    }
  }
  /**
   * Causes this future to report an {@link ExecutionException}
   * with the given throwable as its cause, unless this future has
   * already been set or has been cancelled.
   *
   * <p>This method is invoked internally by the {@link #run} method
   * upon failure of the computation.
   *
   * @param t the cause of failure
   */
  protected void setException(Throwable t) {
    if ((this, stateOffset, NEW, COMPLETING)) {
      outcome = t;
      (this, stateOffset, EXCEPTIONAL); // final state
      finishCompletion();
    }
  }
  /**
   Because the Runnable interface is implemented, the method can be called by the execution thread.
   **/
  public void run() {
    //It will only be run when the task status = new    if (state != NEW ||
      !(this, runnerOffset,
                     null, ()))
      return;
    try {
      Callable<V> c = callable;
      if (c != null && state == NEW) {
        V result;
        boolean ran;
        try {
          //Calling Callable Call method          result = ();
          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);
    }
  }
  /**
   If the task is not cancelled or ends abnormally during execution, the method does not record the execution result of the task and does not modify the task execution status.
   Therefore, the method can be repeated N times.  However, it cannot be called directly because it is protected permission.
   **/
  protected boolean runAndReset() {
    if (state != NEW ||
      !(this, runnerOffset,
                     null, ()))
      return false;
    boolean ran = false;
    int s = state;
    try {
      Callable<V> c = callable;
      if (c != null && s == NEW) {
        try {
          (); // 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;
  }
  /**
   * Ensures that any interrupt from a possible cancel(true) is only
   * delivered to a task while in run or runAndReset.
   */
  private void handlePossibleCancellationInterrupt(int s) {
    // It is possible for our interrupter to stall before getting a
    // chance to interrupt us. Let's spin-wait patiently.
    if (s == INTERRUPTING)
      while (state == INTERRUPTING)
        (); // wait out pending interrupt
    // assert state == INTERRUPTED;
    // We want to clear any interrupt we may have received from
    // cancel(true). However, it is permissible to use interrupts
    // as an independent mechanism for a task to communicate with
    // its caller, and there is no way to clear only the
    // cancellation interrupt.
    //
    // ();
  }
  /**
   * Simple linked list nodes to record waiting threads in a Treiber
   * stack. See other classes such as Phaser and SynchronousQueue
   * for more detailed explanation.
   */
  static final class WaitNode {
    volatile Thread thread;
    volatile WaitNode next;
    WaitNode() { thread = (); }
  }
  /**
   This method is called after the task is completed (including exception completion and cancellation).  Delete all threads that are getting the waiting node and wake up the node.  and call the done method and empty the callable.
   **/
  private void finishCompletion() {
    // assert state > COMPLETING;
    for (WaitNode q; (q = waiters) != null;) {
      if ((this, waitersOffset, q, null)) {
        for (;;) {
          Thread t = ;
          if (t != null) {
             = null;
            (t);
          }
          WaitNode next = ;
          if (next == null)
            break;
           = null; // unlink to help gc
          q = next;
        }
        break;
      }
    }
    done();
    callable = null;    // to reduce footprint
  }
  /**
   Blocking and waiting for task execution to complete (interrupt, normal completion, timeout)
   **/
  private int awaitDone(boolean timed, long nanos)
    throws InterruptedException {
    final long deadline = timed ? () + nanos : 0L;
    WaitNode q = null;
    boolean queued = false;
    for (;;) {
      /**
       The order of if else here is also particular.
       1. First determine whether the thread is interrupted. If the interrupt is removed from the queue (it may also be that the thread does not exist in the queue)
       2. Determine whether the current task is completed. If the execution is completed, it will no longer block and return directly.
       3. If the task status = COMPLETING, it is proved that the task has been executed and the task execution status is being switched, and the CPU can give up for a moment.
       ==null, then prove that no node has been created, then node is created
       Node joining
       6 and 7. Blocking
       **/
      if (()) {
        removeWaiter(q);
        throw new InterruptedException();
      }
      int s = state;
      if (s > COMPLETING) {
        if (q != null)
           = null;
        return s;
      }
      else if (s == COMPLETING) // cannot time out yet
        ();
      else if (q == null)
        q = new WaitNode();
      else if (!queued)
        queued = (this, waitersOffset,
                            = waiters, q);
      else if (timed) {
        nanos = deadline - ();
        if (nanos <= 0L) {
          removeWaiter(q);
          return state;
        }
        (this, nanos);
      }
      else
        (this);
    }
  }
  /**
   * Tries to unlink a timed-out or interrupted wait node to avoid
   * accumulating garbage. Internal nodes are simply unspliced
   * without CAS since it is harmless if they are traversed anyway
   * by releasers. To avoid effects of unsplicing from already
   * removed nodes, the list is retraversed in case of an apparent
   * race. This is slow when there are a lot of nodes, but we don't
   * expect lists to be long enough to outweigh higher-overhead
   * schemes.
   */
  private void removeWaiter(WaitNode node) {
    if (node != null) {
       = null;
      retry:
      for (;;) {     // restart on removeWaiter race
        for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
          s = ;
          if ( != null)
            pred = q;
          else if (pred != null) {
             = s;
            if ( == null) // check for race
              continue retry;
          }
          else if (!(this, waitersOffset,
                             q, s))
            continue retry;
        }
        break;
      }
    }
  }
  // Unsafe mechanics
  private static final  UNSAFE;
  private static final long stateOffset;
  private static final long runnerOffset;
  private static final long waitersOffset;
  static {
    try {
      UNSAFE = ();
      Class<?> k = ;
      stateOffset = 
        (("state"));
      runnerOffset = 
        (("runner"));
      waitersOffset = 
        (("waiters"));
    } catch (Exception e) {
      throw new Error(e);
    }
  }
}

Summarize

The above is all the content of this article about futuretask source code analysis (recommended). I hope it will be helpful to everyone. Interested friends can refer to:Java uses future to obtain multi-threaded running results in timeA brief discussion on the wonderful uses of Future in Java multithreading (with source code)Introduction to futuretask usage and usage scenariosWait, if you have any questions, you can leave a message at any time. Everyone is welcome to communicate and discuss.