/* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain. Use, modify, and * redistribute this code in any way without acknowledgement. */ package java.util.concurrent; /** * A cancellable asynchronous computation. * *

Provides methods to start and cancel the 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 is completed, the result cannot be changed, nor can the * computation be restarted or cancelled. * *

Because FutureTask implements Runnable, a * FutureTask can be submitted to an {@link Executor} for * current or deferred execution. * *

A FutureTask can be used to wrap a Callable or * Runnable object so that it can be scheduled for execution in a * thread or an Executor, cancel * computation before the computation completes, and wait for or * retrieve the results. If the computation threw an exception, the * exception is propagated to any thread that attempts to retrieve the * result. * * @see Executor * * @since 1.5 * @spec JSR-166 * @revised $Date: 2003/06/03 16:44:36 $ * @editor $Author: dl $ */ public class FutureTask extends CancellableTask implements Cancellable, Future, Runnable { /** * Constructs a FutureTask that will upon running, execute the * given Callable. * * @param callable the callable task */ public FutureTask(Callable callable) { // must set after super ctor call to use inner class super(); setRunnable(new InnerCancellableFuture(callable)); } /** * Constructs a FutureTask that will upon running, execute the * given Runnable, and arrange that 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 just using * Boolean.TRUE. */ public FutureTask(final Runnable runnable, final V result) { super(); setRunnable(new InnerCancellableFuture (new Callable() { public V call() { runnable.run(); return result; } })); } /** * Waits if necessary for the computation to complete, and then retrieves * its result. * * @return the computed result * @throws CancellationException if task producing this value was * cancelled before completion * @throws ExecutionException if the underlying computation threw an exception * @throws InterruptedException if current thread was interrupted while waiting */ public V get() throws InterruptedException, ExecutionException { return ((InnerCancellableFuture)getRunnable()).get(); } /** * Waits if necessary for at most the given time for the computation to * complete, and then retrieves its result. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return value of this task * @throws CancellationException if task producing this value was cancelled before completion * @throws ExecutionException if the underlying computation * threw an exception. * @throws InterruptedException if current thread was interrupted while waiting * @throws TimeoutException if the wait timed out */ public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return ((InnerCancellableFuture)getRunnable()).get(timeout, unit); } /** * Sets the value of this task to the given value. This method * should only be called once; once it is called, the computation * is assumed to have completed. * * @param v the value * * @fixme Need to clarify "should" in "should only be called once". */ protected void set(V v) { ((InnerCancellableFuture)getRunnable()).set(v); } /** * Indicates that the computation has failed. After this method * is called, the computation is assumed to be completed, and any * attempt to retrieve the result will throw an ExecutionException * wrapping the exception provided here. * * @param t the throwable */ protected void setException(Throwable t) { ((InnerCancellableFuture)getRunnable()).setException(t); } }