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, 5 months ago) by dl
Branch: MAIN
Changes since 1.17: +5 -1 lines
Log Message:
Documentation improvements

File Contents

# Content
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 */
6
7 package java.util.concurrent;
8 import java.util.concurrent.locks.*;
9
10
11 /**
12 * 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 * 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 * the computation has completed, the computation cannot be restarted
19 * or cancelled.
20 *
21 * <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 *
26 * <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 * @since 1.5
31 * @author Doug Lea
32 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
33 */
34 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
45 /**
46 * 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 */
52 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
60 /** 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
65 /** The result to return from get() */
66 private V result;
67 /** The exception to throw from get() */
68 private Throwable exception;
69
70 private final ReentrantLock lock = new ReentrantLock();
71 private final ReentrantLock.ConditionObject accessible = lock.newCondition();
72
73 /**
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 * @throws NullPointerException if callable is null
79 */
80 public FutureTask(Callable<V> callable) {
81 if (callable == null)
82 throw new NullPointerException();
83 this.callable = callable;
84 this.runnable = null;
85 }
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 * you don't need a particular result, consider using
95 * constructions of the form:
96 * <tt>Future&lt;?&gt; f = new FutureTask&lt;Object&gt;(runnable, null)</tt>
97 * @throws NullPointerException if runnable is null
98 */
99 public FutureTask(Runnable runnable, V result) {
100 if (runnable == null)
101 throw new NullPointerException();
102 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 runner = CANCELLED;
114 if (mayInterruptIfRunning && r != null && r instanceof Thread)
115 ((Thread)r).interrupt();
116 // propagate to nested future
117 Runnable subtask = runnable;
118 if (subtask != null && subtask instanceof Future)
119 ((Future<?>)subtask).cancel(false);
120 }
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 }
136
137 /**
138 * Waits if necessary for execution to complete, and then
139 * retrieves its result.
140 *
141 * @return computed result
142 * @throws CancellationException if underlying computation was
143 * cancelled
144 * @throws ExecutionException if underlying computation threw an
145 * exception
146 * @throws InterruptedException if current thread was interrupted
147 * while waiting
148 */
149 public V get() throws InterruptedException, ExecutionException {
150 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 }
164
165 /**
166 * Waits if necessary for at most the given time for execution to
167 * complete, and then retrieves its result, if available.
168 *
169 * @param timeout the maximum time to wait
170 * @param unit the time unit of the timeout argument
171 * @return computed result
172 * @throws CancellationException if underlying computation was
173 * cancelled
174 * @throws ExecutionException if underlying computation threw an
175 * exception
176 * @throws InterruptedException if current thread was interrupted
177 * while waiting
178 * @throws TimeoutException if the wait timed out
179 */
180 public V get(long timeout, TimeUnit unit)
181 throws InterruptedException, ExecutionException, TimeoutException {
182 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 }
202
203 /**
204 * Sets the result of this Future to the given value.
205 * @param v the value
206 */
207 protected void set(V v) {
208 lock.lock();
209 try {
210 result = v;
211 setDone();
212 accessible.signalAll();
213 } finally {
214 lock.unlock();
215 }
216 }
217
218 /**
219 * 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 protected void setException(Throwable t) {
224 lock.lock();
225 try {
226 exception = t;
227 setDone();
228 accessible.signalAll();
229 } finally {
230 lock.unlock();
231 }
232 }
233
234 /**
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
265 /**
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 * Sets this Future to the results of computation and then resets
305 * to initial state. This may be useful for tasks that intriniscally
306 * 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 * 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
355 /**
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
367 }
368