ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/FutureTask.java
Revision: 1.20
Committed: Mon Dec 22 16:25:20 2003 UTC (20 years, 5 months ago) by dl
Branch: MAIN
Changes since 1.19: +99 -145 lines
Log Message:
Simplify FutureTask and AbstractExecutorService internals; improve docs

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     lock.lock();
104     try {
105 dl 1.20 Object r = runState;
106 dl 1.13 if (r == DONE || r == CANCELLED)
107     return false;
108 dl 1.20 runState = CANCELLED;
109     accessible.signalAll();
110 dl 1.13 if (mayInterruptIfRunning && r != null && r instanceof Thread)
111     ((Thread)r).interrupt();
112     }
113     finally{
114     lock.unlock();
115     }
116     done();
117     return true;
118     }
119    
120 tim 1.1 /**
121 dl 1.17 * Waits if necessary for execution to complete, and then
122     * retrieves its result.
123 tim 1.1 *
124 dl 1.13 * @return computed result
125     * @throws CancellationException if underlying computation was
126     * cancelled
127     * @throws ExecutionException if underlying computation threw an
128     * exception
129 dl 1.4 * @throws InterruptedException if current thread was interrupted
130     * while waiting
131 tim 1.1 */
132 dl 1.2 public V get() throws InterruptedException, ExecutionException {
133 dl 1.13 lock.lock();
134     try {
135 dl 1.20 for (;;) {
136     Object r = runState;
137     if (r == CANCELLED)
138     throw new CancellationException();
139     if (r == DONE) {
140     if (exception != null)
141     throw new ExecutionException(exception);
142     else
143     return result;
144     }
145 dl 1.13 accessible.await();
146 dl 1.20 }
147 dl 1.13 } finally {
148     lock.unlock();
149     }
150 tim 1.1 }
151    
152     /**
153 dl 1.17 * Waits if necessary for at most the given time for execution to
154     * complete, and then retrieves its result, if available.
155 tim 1.1 *
156     * @param timeout the maximum time to wait
157 dl 1.2 * @param unit the time unit of the timeout argument
158 dl 1.13 * @return computed result
159     * @throws CancellationException if underlying computation was
160     * cancelled
161     * @throws ExecutionException if underlying computation threw an
162     * exception
163 dl 1.4 * @throws InterruptedException if current thread was interrupted
164     * while waiting
165 tim 1.1 * @throws TimeoutException if the wait timed out
166     */
167 dl 1.2 public V get(long timeout, TimeUnit unit)
168 tim 1.1 throws InterruptedException, ExecutionException, TimeoutException {
169 dl 1.20 long nanos = unit.toNanos(timeout);
170 dl 1.13 lock.lock();
171     try {
172 dl 1.20 for (;;) {
173     Object r = runState;
174     if (r == CANCELLED)
175     throw new CancellationException();
176     if (r == DONE) {
177     if (exception != null)
178     throw new ExecutionException(exception);
179     else
180     return result;
181     }
182     if (nanos <= 0)
183     throw new TimeoutException();
184     nanos = accessible.awaitNanos(nanos);
185 dl 1.13 }
186     } finally {
187     lock.unlock();
188     }
189 tim 1.1 }
190    
191     /**
192 dl 1.20 * Protected method invoked when this task transitions to state
193     * <tt>isDone</tt> (whether normally or via cancellation). The
194     * default implementation does nothing. Subclasses may override
195     * this method to invoke completion callbacks or perform
196     * bookkeeping. Note that you can query status inside the
197     * implementation of this method to determine whether this task
198     * has been cancelled.
199     */
200     protected void done() { }
201    
202     /**
203     * Sets the result of this Future to the given value unless
204     * this future has been cancelled
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 dl 1.20 if (runState == CANCELLED)
211     return;
212 dl 1.13 result = v;
213 dl 1.20 accessible.signalAll();
214     runState = DONE;
215 dl 1.13 } finally {
216     lock.unlock();
217     }
218 dl 1.20 done();
219 tim 1.1 }
220    
221     /**
222 dl 1.13 * Causes this future to report an <tt>ExecutionException</tt>
223 dl 1.20 * with the given throwable as its cause, unless this Future has
224     * been cancelled.
225 dl 1.13 * @param t the cause of failure.
226     */
227 dl 1.2 protected void setException(Throwable t) {
228 dl 1.13 lock.lock();
229     try {
230 dl 1.20 if (runState == CANCELLED)
231     return;
232 dl 1.13 exception = t;
233 dl 1.20 accessible.signalAll();
234     runState = DONE;
235 dl 1.13 } finally {
236     lock.unlock();
237     }
238 dl 1.20 done();
239 tim 1.1 }
240 dl 1.20
241 dl 1.14 /**
242 dl 1.20 * Attempts to set the state of this task to Running, succeeding
243     * only if the state is currently NOT Done, Running, or Cancelled.
244     * @return true if successful
245     */
246     private boolean setRunning() {
247 dl 1.14 lock.lock();
248     try {
249 dl 1.20 if (runState != null)
250     return false;
251     runState = Thread.currentThread();
252     return true;
253 dl 1.14 }
254 dl 1.20 finally {
255 dl 1.14 lock.unlock();
256     }
257     }
258 dl 1.3
259 dl 1.14 /**
260 dl 1.20 * Resets the run state of this task to its initial state unless
261     * it has been cancelled. (Note that a cancelled task cannot be
262     * reset.)
263 dl 1.14 * @return true if successful
264 dl 1.20 */
265     private boolean reset() {
266 dl 1.14 lock.lock();
267     try {
268 dl 1.20 if (runState == CANCELLED)
269 dl 1.14 return false;
270 dl 1.20 runState = null;
271 dl 1.14 return true;
272     }
273     finally {
274     lock.unlock();
275     }
276     }
277    
278     /**
279 dl 1.20 * Sets this Future to the result of computation unless
280     * it has been cancelled.
281 dl 1.14 */
282     public void run() {
283     if (setRunning()) {
284     try {
285 dl 1.20 set(callable.call());
286 dl 1.19 } catch(Throwable ex) {
287     setException(ex);
288 dl 1.14 }
289     }
290     }
291    
292     /**
293 dl 1.20 * Executes the computation and then resets this Future to initial
294     * state; failing to do so if the computation encounters an
295     * exception or is cancelled. This is designed for use with tasks
296     * that intrinsically execute more than once.
297     * @return true if successfully run and reset
298 dl 1.15 */
299 dl 1.20 protected boolean runAndReset() {
300 dl 1.15 if (setRunning()) {
301     try {
302 dl 1.20 // don't bother to set result; it can't be accessed
303     callable.call();
304     return reset();
305 dl 1.19 } catch(Throwable ex) {
306     setException(ex);
307 dl 1.20 }
308 dl 1.14 }
309 dl 1.20 return false;
310 dl 1.15 }
311 tim 1.1
312 dl 1.15 }
313 tim 1.1