ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.18
Committed: Sun Dec 21 14:55:52 2003 UTC (20 years, 9 months ago) by dl
Branch: MAIN
Changes since 1.17: +5 -1 lines
Log Message:
Documentation improvements

File Contents

# User Rev Content
1 tim 1.1 /*
2 dl 1.2 * Written by Doug Lea with assistance from members of JCP JSR-166
3     * Expert Group and released to the public domain. Use, modify, and
4     * redistribute this code in any way without acknowledgement.
5 tim 1.1 */
6    
7     package java.util.concurrent;
8 dl 1.13 import java.util.concurrent.locks.*;
9    
10 tim 1.1
11     /**
12 dl 1.8 * A cancellable asynchronous computation. This class provides a base
13     * implementation of {@link Future}, with methods to start and cancel
14     * a computation, query to see if the computation is complete, and
15 dl 1.4 * retrieve the result of the computation. The result can only be
16     * retrieved when the computation has completed; the <tt>get</tt>
17     * method will block if the computation has not yet completed. Once
18 dl 1.8 * the computation has completed, the computation cannot be restarted
19     * or cancelled.
20 tim 1.1 *
21 dl 1.8 * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
22     * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
23     * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
24     * submitted to an {@link Executor} for execution.
25 tim 1.1 *
26 dl 1.14 * <p>In addition to serving as a standalone class, this class provides
27     * <tt>protected</tt> functionality that may be useful when creating
28     * customized task classes.
29     *
30 tim 1.1 * @since 1.5
31 dl 1.4 * @author Doug Lea
32 dl 1.12 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
33 tim 1.1 */
34 dl 1.13 public class FutureTask<V> implements Future<V>, Runnable {
35     /**
36     * Special value for "runner" indicating task is cancelled
37     */
38     private static final Object CANCELLED = new Object();
39    
40     /**
41     * Special value for "runner" indicating task is completed
42     */
43     private static final Object DONE = new Object();
44 tim 1.1
45 dl 1.11 /**
46 dl 1.13 * Holds the run-state, taking on values:
47     * null = not yet started,
48     * [some thread ref] = running,
49     * DONE = completed normally,
50     * CANCELLED = cancelled (may or may not have ever run).
51 dl 1.11 */
52 dl 1.14 private volatile Object runner;
53    
54     /*
55     * For simplicity of use, we can use either a Runnable or a
56     * Callable as basis for run method. So one or the other of these
57     * will be null.
58     */
59 dl 1.13
60 dl 1.15 /** The runnable; if non-null, then callable is null */
61     private final Runnable runnable;
62     /** The callable; if non-null, then runnable is null */
63     private final Callable<V> callable;
64 dl 1.14
65     /** The result to return from get() */
66     private V result;
67     /** The exception to throw from get() */
68     private Throwable exception;
69    
70 dl 1.13 private final ReentrantLock lock = new ReentrantLock();
71     private final ReentrantLock.ConditionObject accessible = lock.newCondition();
72 dl 1.11
73 tim 1.1 /**
74     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
75     * given <tt>Callable</tt>.
76     *
77     * @param callable the callable task
78 dl 1.9 * @throws NullPointerException if callable is null
79 tim 1.1 */
80     public FutureTask(Callable<V> callable) {
81 dl 1.9 if (callable == null)
82     throw new NullPointerException();
83 dl 1.13 this.callable = callable;
84     this.runnable = null;
85 tim 1.1 }
86    
87     /**
88     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
89     * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
90     * given result on successful completion.
91     *
92     * @param runnable the runnable task
93     * @param result the result to return on successful completion. If
94 dl 1.9 * you don't need a particular result, consider using
95 dl 1.16 * constructions of the form:
96     * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
97 dl 1.9 * @throws NullPointerException if runnable is null
98 tim 1.1 */
99 dl 1.15 public FutureTask(Runnable runnable, V result) {
100 dl 1.9 if (runnable == null)
101     throw new NullPointerException();
102 dl 1.13 this.runnable = runnable;
103     this.result = result;
104     this.callable = null;
105     }
106    
107     public boolean cancel(boolean mayInterruptIfRunning) {
108     lock.lock();
109     try {
110     Object r = runner;
111     if (r == DONE || r == CANCELLED)
112     return false;
113 dl 1.18 runner = CANCELLED;
114 dl 1.13 if (mayInterruptIfRunning && r != null && r instanceof Thread)
115     ((Thread)r).interrupt();
116 dl 1.18 // propagate to nested future
117     Runnable subtask = runnable;
118     if (subtask != null && subtask instanceof Future)
119     ((Future<?>)subtask).cancel(false);
120 dl 1.13 }
121     finally{
122     lock.unlock();
123     }
124     done();
125     return true;
126     }
127    
128     public boolean isCancelled() {
129     return runner == CANCELLED;
130     }
131    
132     public boolean isDone() {
133     Object r = runner;
134     return r == DONE || r == CANCELLED;
135 tim 1.1 }
136    
137     /**
138 dl 1.17 * Waits if necessary for execution to complete, and then
139     * retrieves its result.
140 tim 1.1 *
141 dl 1.13 * @return computed result
142     * @throws CancellationException if underlying computation was
143     * cancelled
144     * @throws ExecutionException if underlying computation threw an
145     * exception
146 dl 1.4 * @throws InterruptedException if current thread was interrupted
147     * while waiting
148 tim 1.1 */
149 dl 1.2 public V get() throws InterruptedException, ExecutionException {
150 dl 1.13 lock.lock();
151     try {
152     while (!isDone())
153     accessible.await();
154     if (isCancelled())
155     throw new CancellationException();
156     else if (exception != null)
157     throw new ExecutionException(exception);
158     else
159     return result;
160     } finally {
161     lock.unlock();
162     }
163 tim 1.1 }
164    
165     /**
166 dl 1.17 * Waits if necessary for at most the given time for execution to
167     * complete, and then retrieves its result, if available.
168 tim 1.1 *
169     * @param timeout the maximum time to wait
170 dl 1.2 * @param unit the time unit of the timeout argument
171 dl 1.13 * @return computed result
172     * @throws CancellationException if underlying computation was
173     * cancelled
174     * @throws ExecutionException if underlying computation threw an
175     * exception
176 dl 1.4 * @throws InterruptedException if current thread was interrupted
177     * while waiting
178 tim 1.1 * @throws TimeoutException if the wait timed out
179     */
180 dl 1.2 public V get(long timeout, TimeUnit unit)
181 tim 1.1 throws InterruptedException, ExecutionException, TimeoutException {
182 dl 1.13 lock.lock();
183     try {
184     if (!isDone()) {
185     long nanos = unit.toNanos(timeout);
186     do {
187     if (nanos <= 0)
188     throw new TimeoutException();
189     nanos = accessible.awaitNanos(nanos);
190     } while (!isDone());
191     }
192     if (isCancelled())
193     throw new CancellationException();
194     else if (exception != null)
195     throw new ExecutionException(exception);
196     else
197     return result;
198     } finally {
199     lock.unlock();
200     }
201 tim 1.1 }
202    
203     /**
204 dl 1.13 * Sets the result of this Future to the given value.
205 tim 1.1 * @param v the value
206 dl 1.13 */
207 dl 1.2 protected void set(V v) {
208 dl 1.13 lock.lock();
209     try {
210     result = v;
211     setDone();
212     accessible.signalAll();
213     } finally {
214     lock.unlock();
215     }
216 tim 1.1 }
217    
218     /**
219 dl 1.13 * Causes this future to report an <tt>ExecutionException</tt>
220     * with the given throwable as its cause.
221     * @param t the cause of failure.
222     */
223 dl 1.2 protected void setException(Throwable t) {
224 dl 1.13 lock.lock();
225     try {
226     exception = t;
227     setDone();
228     accessible.signalAll();
229     } finally {
230     lock.unlock();
231     }
232 tim 1.1 }
233 dl 1.13
234 dl 1.14 /**
235     * Sets the state of this task to Cancelled.
236     */
237     protected void setCancelled() {
238     lock.lock();
239     try {
240     runner = CANCELLED;
241     }
242     finally{
243     lock.unlock();
244     }
245     }
246    
247     /**
248     * Sets the state of this task to Done, unless already in a
249     * Cancelled state, in which case Cancelled status is preserved.
250     */
251     protected void setDone() {
252     lock.lock();
253     try {
254     Object r = runner;
255     if (r == DONE || r == CANCELLED)
256     return;
257     runner = DONE;
258     }
259     finally{
260     lock.unlock();
261     }
262     done();
263     }
264 dl 1.3
265 dl 1.14 /**
266     * Attempts to set the state of this task to Running, succeeding
267     * only if the state is currently NOT Done, Running, or Cancelled.
268     * @return true if successful
269     */
270     protected boolean setRunning() {
271     lock.lock();
272     try {
273     if (runner != null)
274     return false;
275     runner = Thread.currentThread();
276     return true;
277     }
278     finally {
279     lock.unlock();
280     }
281     }
282    
283     /**
284     * Sets this Future to the results of computation
285     */
286     public void run() {
287     if (setRunning()) {
288     try {
289     try {
290     if (runnable != null)
291     runnable.run();
292     else if (callable != null)
293     set(callable.call());
294     } catch(Throwable ex) {
295     setException(ex);
296     }
297     } finally {
298     setDone();
299     }
300     }
301     }
302    
303     /**
304 dl 1.15 * Sets this Future to the results of computation and then resets
305 dl 1.17 * to initial state. This may be useful for tasks that intriniscally
306 dl 1.15 * execute more than once.
307     */
308     protected void runAndReset() {
309     if (setRunning()) {
310     try {
311     try {
312     if (runnable != null)
313     runnable.run();
314     else if (callable != null)
315     set(callable.call());
316     } catch(Throwable ex) {
317     setException(ex);
318     }
319     } finally {
320     reset();
321     }
322     }
323     }
324    
325     /**
326 dl 1.14 * Protected method invoked when this task transitions to state
327     * <tt>isDone</tt> (whether normally or via cancellation). The
328     * default implementation does nothing. Subclasses may override
329     * this method to invoke completion callbacks or perform
330     * bookkeeping. Note that you can query status inside the
331     * implementation of this method to determine whether this task
332     * has been cancelled.
333     */
334     protected void done() { }
335    
336     /**
337     * Resets the run state of this task to its initial state unless
338     * it has been cancelled. (Note that a cancelled task cannot be
339     * reset.)
340     * @return true if successful
341     */
342     protected boolean reset() {
343     lock.lock();
344     try {
345     if (runner == CANCELLED)
346     return false;
347     runner = null;
348     return true;
349     }
350     finally {
351     lock.unlock();
352     }
353     }
354 tim 1.1
355 dl 1.15 /**
356     * Return the <tt>Runnable</tt> or <tt>Callable</tt> used
357     * in the constructor for this <tt>Future</tt>.
358     * @return the task
359     */
360     protected Object getTask() {
361     if (runnable != null)
362     return runnable;
363     else
364     return callable;
365     }
366 tim 1.1
367 dl 1.15 }
368 tim 1.1