/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * Written by Doug Lea with assistance from members of JCP JSR-166
 * Expert Group and released to the public domain, as explained at
 * http://creativecommons.org/licenses/publicdomain
 */

package java.util.concurrent;
import java.util.concurrent.locks.*;

A cancellable asynchronous computation. This class provides a base implementation of Future, with methods to start and cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed; the get method will block if the computation has not yet completed. Once the computation has completed, the computation cannot be restarted or cancelled.

A FutureTask can be used to wrap a Callable or Runnable object. Because FutureTask implements Runnable, a FutureTask can be submitted to an Executor for execution.

In addition to serving as a standalone class, this class provides protected functionality that may be useful when creating customized task classes.

Author:Doug Lea
Type parameters:
  • <V> – The result type returned by this FutureTask's get method
Since:1.5
/** * A cancellable asynchronous computation. This class provides a base * implementation of {@link Future}, with methods to start and cancel * a computation, query to see if the computation is complete, and * retrieve the result of the computation. The result can only be * retrieved when the computation has completed; the <tt>get</tt> * method will block if the computation has not yet completed. Once * the computation has completed, the computation cannot be restarted * or cancelled. * * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt> * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be * submitted to an {@link Executor} for execution. * * <p>In addition to serving as a standalone class, this class provides * <tt>protected</tt> functionality that may be useful when creating * customized task classes. * * @since 1.5 * @author Doug Lea * @param <V> The result type returned by this FutureTask's <tt>get</tt> method */
public class FutureTask<V> implements RunnableFuture<V> {
Synchronization control for FutureTask
/** Synchronization control for FutureTask */
private final Sync sync;
Creates a FutureTask that will, upon running, execute the given Callable.
Params:
  • callable – the callable task
Throws:
/** * Creates a <tt>FutureTask</tt> that will, upon running, execute the * given <tt>Callable</tt>. * * @param callable the callable task * @throws NullPointerException if callable is null */
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); sync = new Sync(callable); }
Creates a FutureTask that will, upon running, execute the given Runnable, and arrange that get will return the given result on successful completion.
Params:
  • runnable – the runnable task
  • result – the result to return on successful completion. If you don't need a particular result, consider using constructions of the form: Future<?> f = new FutureTask<Object>(runnable, null)
Throws:
/** * Creates a <tt>FutureTask</tt> that will, upon running, execute the * given <tt>Runnable</tt>, and arrange that <tt>get</tt> 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: * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt> * @throws NullPointerException if runnable is null */
public FutureTask(Runnable runnable, V result) { sync = new Sync(Executors.callable(runnable, result)); } public boolean isCancelled() { return sync.innerIsCancelled(); } public boolean isDone() { return sync.innerIsDone(); } public boolean cancel(boolean mayInterruptIfRunning) { return sync.innerCancel(mayInterruptIfRunning); }
Throws:
  • CancellationException – {@inheritDoc}
/** * @throws CancellationException {@inheritDoc} */
public V get() throws InterruptedException, ExecutionException { return sync.innerGet(); }
Throws:
  • CancellationException – {@inheritDoc}
/** * @throws CancellationException {@inheritDoc} */
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return sync.innerGet(unit.toNanos(timeout)); }
Protected method invoked when this task transitions to state 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 method invoked when this task transitions to state * <tt>isDone</tt> (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() { }
Sets the result of this Future to the given value unless this future has already been set or has been cancelled. This method is invoked internally by the run method upon successful completion of the computation.
Params:
  • v – the value
/** * Sets the result of this Future to the given value unless * this future has already been set or has been cancelled. * This method is invoked internally by the <tt>run</tt> method * upon successful completion of the computation. * @param v the value */
protected void set(V v) { sync.innerSet(v); }
Causes this future to report an ExecutionException with the given throwable as its cause, unless this Future has already been set or has been cancelled. This method is invoked internally by the run method upon failure of the computation.
Params:
  • t – the cause of failure
/** * Causes this future to report an <tt>ExecutionException</tt> * with the given throwable as its cause, unless this Future has * already been set or has been cancelled. * This method is invoked internally by the <tt>run</tt> method * upon failure of the computation. * @param t the cause of failure */
protected void setException(Throwable t) { sync.innerSetException(t); } // The following (duplicated) doc comment can be removed once // // 6270645: Javadoc comments should be inherited from most derived // superinterface or superclass // is fixed.
Sets this Future to the result of its computation unless it has been cancelled.
/** * Sets this Future to the result of its computation * unless it has been cancelled. */
public void run() { sync.innerRun(); }
Executes the computation without setting its result, and then resets this Future to initial state, failing to do so if the computation encounters an exception or is cancelled. This is designed for use with tasks that intrinsically execute more than once.
Returns:true if successfully run and reset
/** * Executes the computation without setting its result, and then * resets this Future to initial state, failing to do so if the * computation encounters an exception or is cancelled. This is * designed for use with tasks that intrinsically execute more * than once. * @return true if successfully run and reset */
protected boolean runAndReset() { return sync.innerRunAndReset(); }
Synchronization control for FutureTask. Note that this must be a non-static inner class in order to invoke the protected done method. For clarity, all inner class support methods are same as outer, prefixed with "inner". Uses AQS sync state to represent run status
/** * Synchronization control for FutureTask. Note that this must be * a non-static inner class in order to invoke the protected * <tt>done</tt> method. For clarity, all inner class support * methods are same as outer, prefixed with "inner". * * Uses AQS sync state to represent run status */
private final class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -7828117401763700385L;
State value representing that task is ready to run
/** State value representing that task is ready to run */
private static final int READY = 0;
State value representing that task is running
/** State value representing that task is running */
private static final int RUNNING = 1;
State value representing that task ran
/** State value representing that task ran */
private static final int RAN = 2;
State value representing that task was cancelled
/** State value representing that task was cancelled */
private static final int CANCELLED = 4;
The underlying callable
/** The underlying callable */
private final Callable<V> callable;
The result to return from get()
/** The result to return from get() */
private V result;
The exception to throw from get()
/** The exception to throw from get() */
private Throwable exception;
The thread running task. When nulled after set/cancel, this indicates that the results are accessible. Must be volatile, to ensure visibility upon completion.
/** * The thread running task. When nulled after set/cancel, this * indicates that the results are accessible. Must be * volatile, to ensure visibility upon completion. */
private volatile Thread runner; Sync(Callable<V> callable) { this.callable = callable; } private boolean ranOrCancelled(int state) { return (state & (RAN | CANCELLED)) != 0; }
Implements AQS base acquire to succeed if ran or cancelled
/** * Implements AQS base acquire to succeed if ran or cancelled */
protected int tryAcquireShared(int ignore) { return innerIsDone() ? 1 : -1; }
Implements AQS base release to always signal after setting final done status by nulling runner thread.
/** * Implements AQS base release to always signal after setting * final done status by nulling runner thread. */
protected boolean tryReleaseShared(int ignore) { runner = null; return true; } boolean innerIsCancelled() { return getState() == CANCELLED; } boolean innerIsDone() { return ranOrCancelled(getState()) && runner == null; } V innerGet() throws InterruptedException, ExecutionException { acquireSharedInterruptibly(0); if (getState() == CANCELLED) throw new CancellationException(); if (exception != null) throw new ExecutionException(exception); return result; } V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException { if (!tryAcquireSharedNanos(0, nanosTimeout)) throw new TimeoutException(); if (getState() == CANCELLED) throw new CancellationException(); if (exception != null) throw new ExecutionException(exception); return result; } void innerSet(V v) { for (;;) { int s = getState(); if (s == RAN) return; if (s == CANCELLED) { // aggressively release to set runner to null, // in case we are racing with a cancel request // that will try to interrupt runner releaseShared(0); return; } if (compareAndSetState(s, RAN)) { result = v; releaseShared(0); done(); return; } } } void innerSetException(Throwable t) { for (;;) { int s = getState(); if (s == RAN) return; if (s == CANCELLED) { // aggressively release to set runner to null, // in case we are racing with a cancel request // that will try to interrupt runner releaseShared(0); return; } if (compareAndSetState(s, RAN)) { exception = t; releaseShared(0); done(); return; } } } boolean innerCancel(boolean mayInterruptIfRunning) { for (;;) { int s = getState(); if (ranOrCancelled(s)) return false; if (compareAndSetState(s, CANCELLED)) break; } if (mayInterruptIfRunning) { Thread r = runner; if (r != null) r.interrupt(); } releaseShared(0); done(); return true; } void innerRun() { if (!compareAndSetState(READY, RUNNING)) return; runner = Thread.currentThread(); if (getState() == RUNNING) { // recheck after setting thread V result; try { result = callable.call(); } catch (Throwable ex) { setException(ex); return; } set(result); } else { releaseShared(0); // cancel } } boolean innerRunAndReset() { if (!compareAndSetState(READY, RUNNING)) return false; try { runner = Thread.currentThread(); if (getState() == RUNNING) callable.call(); // don't set result runner = null; return compareAndSetState(RUNNING, READY); } catch (Throwable ex) { setException(ex); return false; } } } }