/*
* 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.
*
*
FutureTask 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/25 08:45:43 $
* @editor $Author: jozart $
* @author Doug Lea
*/
public class FutureTask extends CancellableTask implements Future {
/**
* 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);
}
}