ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.15
Committed: Fri Dec 5 11:57:52 2003 UTC (20 years, 6 months ago) by dl
Branch: MAIN
CVS Tags: JSR166_DEC9_PRE_ES_SUBMIT, JSR166_DEC9_POST_ES_SUBMIT
Changes since 1.14: +39 -13 lines
Log Message:
Avoid needing package-private fields

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