ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.21
Committed: Tue Dec 23 19:38:09 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.20: +13 -3 lines
Log Message:
cache finals across volatiles; avoid readResolve; doc improvments; timed invokeAll interleaves

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 dl 1.20 * Special value for "runState" indicating task is cancelled
37 dl 1.13 */
38     private static final Object CANCELLED = new Object();
39    
40     /**
41 dl 1.20 * Special value for "runState" indicating task is completed
42 dl 1.13 */
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.20 private volatile Object runState;
53 dl 1.14
54 dl 1.20 /** The underlying callable */
55 dl 1.15 private final Callable<V> callable;
56 dl 1.14 /** The result to return from get() */
57     private V result;
58     /** The exception to throw from get() */
59     private Throwable exception;
60    
61 dl 1.13 private final ReentrantLock lock = new ReentrantLock();
62     private final ReentrantLock.ConditionObject accessible = lock.newCondition();
63 dl 1.11
64 tim 1.1 /**
65     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
66     * given <tt>Callable</tt>.
67     *
68     * @param callable the callable task
69 dl 1.9 * @throws NullPointerException if callable is null
70 tim 1.1 */
71     public FutureTask(Callable<V> callable) {
72 dl 1.9 if (callable == null)
73     throw new NullPointerException();
74 dl 1.13 this.callable = callable;
75 tim 1.1 }
76    
77     /**
78     * Constructs a <tt>FutureTask</tt> that will upon running, execute the
79     * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
80     * given result on successful completion.
81     *
82     * @param runnable the runnable task
83     * @param result the result to return on successful completion. If
84 dl 1.9 * you don't need a particular result, consider using
85 dl 1.16 * constructions of the form:
86     * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
87 dl 1.9 * @throws NullPointerException if runnable is null
88 tim 1.1 */
89 dl 1.15 public FutureTask(Runnable runnable, V result) {
90 dl 1.20 this.callable = Executors.callable(runnable, result);
91     }
92    
93     public boolean isCancelled() {
94     return runState == CANCELLED;
95     }
96    
97     public boolean isDone() {
98     Object r = runState;
99     return r == DONE || r == CANCELLED;
100 dl 1.13 }
101    
102     public boolean cancel(boolean mayInterruptIfRunning) {
103 dl 1.21 final ReentrantLock lock = this.lock;
104     Thread interruptThread = null;
105 dl 1.13 lock.lock();
106     try {
107 dl 1.20 Object r = runState;
108 dl 1.13 if (r == DONE || r == CANCELLED)
109     return false;
110 dl 1.21 if (mayInterruptIfRunning && r != null && r instanceof Thread)
111     interruptThread = (Thread)r;
112     accessible.signalAll();
113 dl 1.20 runState = CANCELLED;
114 dl 1.13 }
115     finally{
116     lock.unlock();
117     }
118 dl 1.21 if (interruptThread != null)
119     interruptThread.interrupt();
120 dl 1.13 done();
121     return true;
122     }
123    
124 tim 1.1 /**
125 dl 1.17 * Waits if necessary for execution to complete, and then
126     * retrieves its result.
127 tim 1.1 *
128 dl 1.13 * @return computed result
129     * @throws CancellationException if underlying computation was
130     * cancelled
131     * @throws ExecutionException if underlying computation threw an
132     * exception
133 dl 1.4 * @throws InterruptedException if current thread was interrupted
134     * while waiting
135 tim 1.1 */
136 dl 1.2 public V get() throws InterruptedException, ExecutionException {
137 dl 1.21 final ReentrantLock lock = this.lock;
138 dl 1.13 lock.lock();
139     try {
140 dl 1.20 for (;;) {
141     Object r = runState;
142     if (r == CANCELLED)
143     throw new CancellationException();
144     if (r == DONE) {
145     if (exception != null)
146     throw new ExecutionException(exception);
147     else
148     return result;
149     }
150 dl 1.13 accessible.await();
151 dl 1.20 }
152 dl 1.13 } finally {
153     lock.unlock();
154     }
155 tim 1.1 }
156    
157     /**
158 dl 1.17 * Waits if necessary for at most the given time for execution to
159     * complete, and then retrieves its result, if available.
160 tim 1.1 *
161     * @param timeout the maximum time to wait
162 dl 1.2 * @param unit the time unit of the timeout argument
163 dl 1.13 * @return computed result
164     * @throws CancellationException if underlying computation was
165     * cancelled
166     * @throws ExecutionException if underlying computation threw an
167     * exception
168 dl 1.4 * @throws InterruptedException if current thread was interrupted
169     * while waiting
170 tim 1.1 * @throws TimeoutException if the wait timed out
171     */
172 dl 1.2 public V get(long timeout, TimeUnit unit)
173 tim 1.1 throws InterruptedException, ExecutionException, TimeoutException {
174 dl 1.20 long nanos = unit.toNanos(timeout);
175 dl 1.21 final ReentrantLock lock = this.lock;
176 dl 1.13 lock.lock();
177     try {
178 dl 1.20 for (;;) {
179     Object r = runState;
180     if (r == CANCELLED)
181     throw new CancellationException();
182     if (r == DONE) {
183     if (exception != null)
184     throw new ExecutionException(exception);
185     else
186     return result;
187     }
188     if (nanos <= 0)
189     throw new TimeoutException();
190     nanos = accessible.awaitNanos(nanos);
191 dl 1.13 }
192     } finally {
193     lock.unlock();
194     }
195 tim 1.1 }
196    
197     /**
198 dl 1.20 * Protected method invoked when this task transitions to state
199     * <tt>isDone</tt> (whether normally or via cancellation). The
200     * default implementation does nothing. Subclasses may override
201     * this method to invoke completion callbacks or perform
202     * bookkeeping. Note that you can query status inside the
203     * implementation of this method to determine whether this task
204     * has been cancelled.
205     */
206     protected void done() { }
207    
208     /**
209     * Sets the result of this Future to the given value unless
210     * this future has been cancelled
211 tim 1.1 * @param v the value
212 dl 1.13 */
213 dl 1.2 protected void set(V v) {
214 dl 1.21 final ReentrantLock lock = this.lock;
215 dl 1.13 lock.lock();
216     try {
217 dl 1.20 if (runState == CANCELLED)
218     return;
219 dl 1.13 result = v;
220 dl 1.20 accessible.signalAll();
221     runState = DONE;
222 dl 1.13 } finally {
223     lock.unlock();
224     }
225 dl 1.20 done();
226 tim 1.1 }
227    
228     /**
229 dl 1.13 * Causes this future to report an <tt>ExecutionException</tt>
230 dl 1.20 * with the given throwable as its cause, unless this Future has
231     * been cancelled.
232 dl 1.13 * @param t the cause of failure.
233     */
234 dl 1.2 protected void setException(Throwable t) {
235 dl 1.21 final ReentrantLock lock = this.lock;
236 dl 1.13 lock.lock();
237     try {
238 dl 1.20 if (runState == CANCELLED)
239     return;
240 dl 1.13 exception = t;
241 dl 1.20 accessible.signalAll();
242     runState = DONE;
243 dl 1.13 } finally {
244     lock.unlock();
245     }
246 dl 1.20 done();
247 tim 1.1 }
248 dl 1.20
249 dl 1.14 /**
250 dl 1.20 * Attempts to set the state of this task to Running, succeeding
251     * only if the state is currently NOT Done, Running, or Cancelled.
252     * @return true if successful
253     */
254     private boolean setRunning() {
255 dl 1.21 final ReentrantLock lock = this.lock;
256 dl 1.14 lock.lock();
257     try {
258 dl 1.20 if (runState != null)
259     return false;
260     runState = Thread.currentThread();
261     return true;
262 dl 1.14 }
263 dl 1.20 finally {
264 dl 1.14 lock.unlock();
265     }
266     }
267 dl 1.3
268 dl 1.14 /**
269 dl 1.20 * Resets the run state of this task to its initial state unless
270     * it has been cancelled. (Note that a cancelled task cannot be
271     * reset.)
272 dl 1.14 * @return true if successful
273 dl 1.20 */
274     private boolean reset() {
275 dl 1.21 final ReentrantLock lock = this.lock;
276 dl 1.14 lock.lock();
277     try {
278 dl 1.20 if (runState == CANCELLED)
279 dl 1.14 return false;
280 dl 1.20 runState = null;
281 dl 1.14 return true;
282     }
283     finally {
284     lock.unlock();
285     }
286     }
287    
288     /**
289 dl 1.20 * Sets this Future to the result of computation unless
290     * it has been cancelled.
291 dl 1.14 */
292     public void run() {
293     if (setRunning()) {
294     try {
295 dl 1.20 set(callable.call());
296 dl 1.19 } catch(Throwable ex) {
297     setException(ex);
298 dl 1.14 }
299     }
300     }
301    
302     /**
303 dl 1.20 * Executes the computation and then resets this Future to initial
304     * state; failing to do so if the computation encounters an
305     * exception or is cancelled. This is designed for use with tasks
306     * that intrinsically execute more than once.
307     * @return true if successfully run and reset
308 dl 1.15 */
309 dl 1.20 protected boolean runAndReset() {
310 dl 1.15 if (setRunning()) {
311     try {
312 dl 1.20 // don't bother to set result; it can't be accessed
313     callable.call();
314     return reset();
315 dl 1.19 } catch(Throwable ex) {
316     setException(ex);
317 dl 1.20 }
318 dl 1.14 }
319 dl 1.20 return false;
320 dl 1.15 }
321 tim 1.1
322 dl 1.15 }
323 tim 1.1