ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.16
Committed: Fri Dec 19 14:42:25 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.15: +2 -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     if (mayInterruptIfRunning && r != null && r instanceof Thread)
114     ((Thread)r).interrupt();
115     runner = CANCELLED;
116     }
117     finally{
118     lock.unlock();
119     }
120     done();
121     return true;
122     }
123    
124     public boolean isCancelled() {
125     return runner == CANCELLED;
126     }
127    
128     public boolean isDone() {
129     Object r = runner;
130     return r == DONE || r == CANCELLED;
131 tim 1.1 }
132    
133     /**
134 dl 1.13 * Waits if necessary for the call to <tt>callable.call</tt> to
135     * complete, and then retrieves its result.
136 tim 1.1 *
137 dl 1.13 * @return computed result
138     * @throws CancellationException if underlying computation was
139     * cancelled
140     * @throws ExecutionException if underlying computation threw an
141     * exception
142 dl 1.4 * @throws InterruptedException if current thread was interrupted
143     * while waiting
144 tim 1.1 */
145 dl 1.2 public V get() throws InterruptedException, ExecutionException {
146 dl 1.13 lock.lock();
147     try {
148     while (!isDone())
149     accessible.await();
150     if (isCancelled())
151     throw new CancellationException();
152     else if (exception != null)
153     throw new ExecutionException(exception);
154     else
155     return result;
156     } finally {
157     lock.unlock();
158     }
159 tim 1.1 }
160    
161     /**
162 dl 1.13 * Waits if necessary for at most the given time for the call to
163     * <tt>callable.call</tt> to complete, and then retrieves its
164     * result.
165 tim 1.1 *
166     * @param timeout the maximum time to wait
167 dl 1.2 * @param unit the time unit of the timeout argument
168 dl 1.13 * @return computed result
169     * @throws CancellationException if underlying computation was
170     * cancelled
171     * @throws ExecutionException if underlying computation threw an
172     * exception
173 dl 1.4 * @throws InterruptedException if current thread was interrupted
174     * while waiting
175 tim 1.1 * @throws TimeoutException if the wait timed out
176     */
177 dl 1.2 public V get(long timeout, TimeUnit unit)
178 tim 1.1 throws InterruptedException, ExecutionException, TimeoutException {
179 dl 1.13 lock.lock();
180     try {
181     if (!isDone()) {
182     long nanos = unit.toNanos(timeout);
183     do {
184     if (nanos <= 0)
185     throw new TimeoutException();
186     nanos = accessible.awaitNanos(nanos);
187     } while (!isDone());
188     }
189     if (isCancelled())
190     throw new CancellationException();
191     else if (exception != null)
192     throw new ExecutionException(exception);
193     else
194     return result;
195     } finally {
196     lock.unlock();
197     }
198 tim 1.1 }
199    
200     /**
201 dl 1.13 * Sets the result of this Future to the given value.
202 tim 1.1 * @param v the value
203 dl 1.13 */
204 dl 1.2 protected void set(V v) {
205 dl 1.13 lock.lock();
206     try {
207     result = v;
208     setDone();
209     accessible.signalAll();
210     } finally {
211     lock.unlock();
212     }
213 tim 1.1 }
214    
215     /**
216 dl 1.13 * Causes this future to report an <tt>ExecutionException</tt>
217     * with the given throwable as its cause.
218     * @param t the cause of failure.
219     */
220 dl 1.2 protected void setException(Throwable t) {
221 dl 1.13 lock.lock();
222     try {
223     exception = t;
224     setDone();
225     accessible.signalAll();
226     } finally {
227     lock.unlock();
228     }
229 tim 1.1 }
230 dl 1.13
231 dl 1.14 /**
232     * Sets the state of this task to Cancelled.
233     */
234     protected void setCancelled() {
235     lock.lock();
236     try {
237     runner = CANCELLED;
238     }
239     finally{
240     lock.unlock();
241     }
242     }
243    
244     /**
245     * Sets the state of this task to Done, unless already in a
246     * Cancelled state, in which case Cancelled status is preserved.
247     */
248     protected void setDone() {
249     lock.lock();
250     try {
251     Object r = runner;
252     if (r == DONE || r == CANCELLED)
253     return;
254     runner = DONE;
255     }
256     finally{
257     lock.unlock();
258     }
259     done();
260     }
261 dl 1.3
262 dl 1.14 /**
263     * Attempts to set the state of this task to Running, succeeding
264     * only if the state is currently NOT Done, Running, or Cancelled.
265     * @return true if successful
266     */
267     protected boolean setRunning() {
268     lock.lock();
269     try {
270     if (runner != null)
271     return false;
272     runner = Thread.currentThread();
273     return true;
274     }
275     finally {
276     lock.unlock();
277     }
278     }
279    
280     /**
281     * Sets this Future to the results of computation
282     */
283     public void run() {
284     if (setRunning()) {
285     try {
286     try {
287     if (runnable != null)
288     runnable.run();
289     else if (callable != null)
290     set(callable.call());
291     } catch(Throwable ex) {
292     setException(ex);
293     }
294     } finally {
295     setDone();
296     }
297     }
298     }
299    
300     /**
301 dl 1.15 * Sets this Future to the results of computation and then resets
302     * to initial state. This may be useful for tasks that must
303     * execute more than once.
304     */
305     protected void runAndReset() {
306     if (setRunning()) {
307     try {
308     try {
309     if (runnable != null)
310     runnable.run();
311     else if (callable != null)
312     set(callable.call());
313     } catch(Throwable ex) {
314     setException(ex);
315     }
316     } finally {
317     reset();
318     }
319     }
320     }
321    
322     /**
323 dl 1.14 * Protected method invoked when this task transitions to state
324     * <tt>isDone</tt> (whether normally or via cancellation). The
325     * default implementation does nothing. Subclasses may override
326     * this method to invoke completion callbacks or perform
327     * bookkeeping. Note that you can query status inside the
328     * implementation of this method to determine whether this task
329     * has been cancelled.
330     */
331     protected void done() { }
332    
333     /**
334     * Resets the run state of this task to its initial state unless
335     * it has been cancelled. (Note that a cancelled task cannot be
336     * reset.)
337     * @return true if successful
338     */
339     protected boolean reset() {
340     lock.lock();
341     try {
342     if (runner == CANCELLED)
343     return false;
344     runner = null;
345     return true;
346     }
347     finally {
348     lock.unlock();
349     }
350     }
351 tim 1.1
352 dl 1.15 /**
353     * Return the <tt>Runnable</tt> or <tt>Callable</tt> used
354     * in the constructor for this <tt>Future</tt>.
355     * @return the task
356     */
357     protected Object getTask() {
358     if (runnable != null)
359     return runnable;
360     else
361     return callable;
362     }
363 tim 1.1
364 dl 1.15 }
365 tim 1.1