ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.1
Committed: Wed May 14 21:30:47 2003 UTC (21 years, 1 month ago) by tim
Branch: MAIN
Log Message:
Moved main source rooted at . to ./src/main
Moved test source rooted at ./etc/testcases to ./src/test

File Contents

# User Rev Content
1 tim 1.1 /*
2     * @(#)FutureTask.java
3     */
4    
5     package java.util.concurrent;
6    
7     /**
8     * A cancellable asynchronous computation.
9     *
10     * <p>Provides methods to start and cancel the computation, query to see if
11     * the computation is complete, and retrieve the result of the computation.
12     * The result can only be retrieved when the computation has completed;
13     * the <tt>get</tt> method will block if the computation has not yet completed.
14     * Once the computation is completed, the result cannot be changed, nor can the
15     * computation be restarted or cancelled.
16     *
17     * <p>Because <tt>FutureTask</tt> implements <tt>Runnable</tt>, a
18     * <tt>FutureTask</tt> can be submitted to an {@link Executor} for
19     * current or deferred execution.
20     *
21     * <p>A <tt>FutureTask</tt> can be used to wrap a <tt>Callable</tt> or
22     * <tt>Runnable</tt> object so that it can be scheduled for execution in a
23     * thread or an <tt>Executor</tt>, cancel
24     * computation before the computation completes, and wait for or
25     * retrieve the results. If the computation threw an exception, the
26     * exception is propagated to any thread that attempts to retrieve the
27     * result.
28     *
29     * @see Executor
30     *
31     * @since 1.5
32     * @spec JSR-166
33     * @revised $Date: 2003/03/31 03:50:08 $
34     * @editor $Author: dholmes $
35     */
36     public class FutureTask<V> implements Cancellable, Future<V>, Runnable {
37    
38     private V result;
39     private Throwable exception;
40     private boolean ready;
41     private Thread runner;
42     private final Callable<V> callable;
43     private boolean cancelled;
44    
45     /**
46     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
47     * given <tt>Callable</tt>.
48     *
49     * @param callable the callable task
50     */
51     public FutureTask(Callable<V> callable) {
52     this.callable = callable;
53     }
54    
55     /**
56     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
57     * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
58     * given result on successful completion.
59     *
60     * @param runnable the runnable task
61     * @param result the result to return on successful completion. If
62     * you don't need a particular result, consider just using
63     * <tt>Boolean.TRUE</tt>.
64     */
65     public FutureTask(final Runnable runnable, final V result) {
66     callable = new Callable<V>() {
67     public V call() {
68     runnable.run();
69     return result;
70     }
71     };
72     }
73    
74     /* Runnable implementation. */
75    
76     /** Starts the computation. */
77     public void run() {
78     doRun();
79     }
80    
81     /**
82     * Executes the callable if not already cancelled or running, and
83     * sets the value or exception with its results.
84     */
85     protected void doRun() {
86     try {
87     synchronized(this) {
88     if (ready || runner != null)
89     return;
90     runner = Thread.currentThread();
91     }
92     set(callable.call());
93     }
94     catch(Throwable ex) {
95     setException(ex);
96     }
97     }
98    
99     /* Future implementation. INHERIT this javadoc from interface??? Note CancellationException. */
100    
101     /**
102     * Waits if necessary for the computation to complete, and then retrieves
103     * its result.
104     *
105     * @return the computed result
106     * @throws CancellationException if task producing this value was
107     * cancelled before completion
108     * @throws ExecutionException if the underlying computation threw an exception
109     * @throws InterruptedException if current thread was interrupted while waiting
110     */
111     public synchronized V get() throws InterruptedException, ExecutionException {
112     while (!ready)
113     wait();
114     if (cancelled)
115     throw new CancellationException();
116     else if (exception != null)
117     throw new ExecutionException(exception);
118     else
119     return result;
120     }
121    
122     /**
123     * Waits if necessary for at most the given time for the computation to
124     * complete, and then retrieves its result.
125     *
126     * @param timeout the maximum time to wait
127     * @param granularity the time unit of the timeout argument
128     * @return value of this task
129     * @throws CancellationException if task producing this value was cancelled before completion
130     * @throws ExecutionException if the underlying computation
131     * threw an exception.
132     * @throws InterruptedException if current thread was interrupted while waiting
133     * @throws TimeoutException if the wait timed out
134     */
135     public synchronized V get(long timeout, TimeUnit granularity)
136     throws InterruptedException, ExecutionException, TimeoutException {
137    
138     if (!ready) {
139     long startTime = TimeUnit.highResolutionTime();
140     long waitTime = timeout;
141     for (;;) {
142     granularity.timedWait(this, waitTime);
143     if (ready)
144     break;
145     else {
146     waitTime = TimeUnit.highResolutionTime() - startTime;
147     if (waitTime <= 0)
148     throw new TimeoutException();
149     }
150     }
151     }
152     if (cancelled)
153     throw new CancellationException();
154     else if (exception != null)
155     throw new ExecutionException(exception);
156     else
157     return result;
158     }
159    
160     /**
161     * Sets the value of this task to the given value. This method
162     * should only be called once; once it is called, the computation
163     * is assumed to have completed.
164     *
165     * @param v the value
166     *
167     * @fixme Need to clarify "should" in "should only be called once".
168     */
169     protected synchronized void set(V v) {
170     ready = true;
171     result = v;
172     runner = null;
173     notifyAll();
174     }
175    
176     /**
177     * Indicates that the computation has failed. After this method
178     * is called, the computation is assumed to be completed, and any
179     * attempt to retrieve the result will throw an <tt>ExecutionException</tt>
180     * wrapping the exception provided here.
181     *
182     * @param t the throwable
183     */
184     protected synchronized void setException(Throwable t) {
185     ready = true;
186     exception = t;
187     runner = null;
188     notifyAll();
189     }
190    
191     /* Cancellable implementation. */
192    
193     public synchronized boolean cancel(boolean mayInterruptIfRunning) {
194     if (ready || cancelled)
195     return false;
196     if (mayInterruptIfRunning &&
197     runner != null && runner != Thread.currentThread())
198     runner.interrupt();
199     return cancelled = ready = true;
200     }
201    
202     public synchronized boolean isCancelled() {
203     return cancelled;
204     }
205    
206     public synchronized boolean isDone() {
207     return ready;
208     }
209     }
210    
211    
212    
213    
214    
215    
216    
217    
218    
219