Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/src/share/classes/java/util/concurrent/FutureTask.java
+++ new/src/share/classes/java/util/concurrent/FutureTask.java
1 1 /*
2 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 3 *
4 4 * This code is free software; you can redistribute it and/or modify it
5 5 * under the terms of the GNU General Public License version 2 only, as
6 6 * published by the Free Software Foundation. Oracle designates this
7 7 * particular file as subject to the "Classpath" exception as provided
8 8 * by Oracle in the LICENSE file that accompanied this code.
9 9 *
10 10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 13 * version 2 for more details (a copy is included in the LICENSE file that
14 14 * accompanied this code).
15 15 *
16 16 * You should have received a copy of the GNU General Public License version
17 17 * 2 along with this work; if not, write to the Free Software Foundation,
18 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 19 *
20 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 21 * or visit www.oracle.com if you need additional information or have any
22 22 * questions.
23 23 */
24 24
25 25 /*
26 26 * This file is available under and governed by the GNU General Public
27 27 * License version 2 only, as published by the Free Software Foundation.
28 28 * However, the following notice accompanied the original version of this
29 29 * file:
30 30 *
31 31 * Written by Doug Lea with assistance from members of JCP JSR-166
32 32 * Expert Group and released to the public domain, as explained at
33 33 * http://creativecommons.org/licenses/publicdomain
34 34 */
35 35
36 36 package java.util.concurrent;
37 37 import java.util.concurrent.locks.*;
38 38
39 39 /**
40 40 * A cancellable asynchronous computation. This class provides a base
41 41 * implementation of {@link Future}, with methods to start and cancel
42 42 * a computation, query to see if the computation is complete, and
43 43 * retrieve the result of the computation. The result can only be
44 44 * retrieved when the computation has completed; the <tt>get</tt>
45 45 * method will block if the computation has not yet completed. Once
46 46 * the computation has completed, the computation cannot be restarted
47 47 * or cancelled.
48 48 *
49 49 * <p>A <tt>FutureTask</tt> can be used to wrap a {@link Callable} or
50 50 * {@link java.lang.Runnable} object. Because <tt>FutureTask</tt>
51 51 * implements <tt>Runnable</tt>, a <tt>FutureTask</tt> can be
52 52 * submitted to an {@link Executor} for execution.
53 53 *
54 54 * <p>In addition to serving as a standalone class, this class provides
55 55 * <tt>protected</tt> functionality that may be useful when creating
56 56 * customized task classes.
57 57 *
58 58 * @since 1.5
59 59 * @author Doug Lea
60 60 * @param <V> The result type returned by this FutureTask's <tt>get</tt> method
61 61 */
62 62 public class FutureTask<V> implements RunnableFuture<V> {
63 63 /** Synchronization control for FutureTask */
64 64 private final Sync sync;
65 65
66 66 /**
67 67 * Creates a <tt>FutureTask</tt> that will, upon running, execute the
68 68 * given <tt>Callable</tt>.
69 69 *
70 70 * @param callable the callable task
71 71 * @throws NullPointerException if callable is null
72 72 */
73 73 public FutureTask(Callable<V> callable) {
74 74 if (callable == null)
75 75 throw new NullPointerException();
76 76 sync = new Sync(callable);
77 77 }
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
78 78
79 79 /**
80 80 * Creates a <tt>FutureTask</tt> that will, upon running, execute the
81 81 * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the
82 82 * given result on successful completion.
83 83 *
84 84 * @param runnable the runnable task
85 85 * @param result the result to return on successful completion. If
86 86 * you don't need a particular result, consider using
87 87 * constructions of the form:
88 - * <tt>Future<?> f = new FutureTask<Object>(runnable, null)</tt>
88 + * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
89 89 * @throws NullPointerException if runnable is null
90 90 */
91 91 public FutureTask(Runnable runnable, V result) {
92 92 sync = new Sync(Executors.callable(runnable, result));
93 93 }
94 94
95 95 public boolean isCancelled() {
96 96 return sync.innerIsCancelled();
97 97 }
98 98
99 99 public boolean isDone() {
100 100 return sync.innerIsDone();
101 101 }
102 102
103 103 public boolean cancel(boolean mayInterruptIfRunning) {
104 104 return sync.innerCancel(mayInterruptIfRunning);
105 105 }
106 106
107 107 /**
108 108 * @throws CancellationException {@inheritDoc}
109 109 */
110 110 public V get() throws InterruptedException, ExecutionException {
111 111 return sync.innerGet();
112 112 }
113 113
114 114 /**
115 115 * @throws CancellationException {@inheritDoc}
116 116 */
117 117 public V get(long timeout, TimeUnit unit)
118 118 throws InterruptedException, ExecutionException, TimeoutException {
119 119 return sync.innerGet(unit.toNanos(timeout));
120 120 }
121 121
122 122 /**
123 123 * Protected method invoked when this task transitions to state
124 124 * <tt>isDone</tt> (whether normally or via cancellation). The
125 125 * default implementation does nothing. Subclasses may override
126 126 * this method to invoke completion callbacks or perform
127 127 * bookkeeping. Note that you can query status inside the
128 128 * implementation of this method to determine whether this task
129 129 * has been cancelled.
130 130 */
131 131 protected void done() { }
132 132
133 133 /**
134 134 * Sets the result of this Future to the given value unless
135 135 * this future has already been set or has been cancelled.
136 136 * This method is invoked internally by the <tt>run</tt> method
137 137 * upon successful completion of the computation.
138 138 * @param v the value
139 139 */
140 140 protected void set(V v) {
141 141 sync.innerSet(v);
142 142 }
143 143
144 144 /**
145 145 * Causes this future to report an <tt>ExecutionException</tt>
146 146 * with the given throwable as its cause, unless this Future has
147 147 * already been set or has been cancelled.
148 148 * This method is invoked internally by the <tt>run</tt> method
149 149 * upon failure of the computation.
150 150 * @param t the cause of failure
151 151 */
152 152 protected void setException(Throwable t) {
153 153 sync.innerSetException(t);
154 154 }
155 155
156 156 // The following (duplicated) doc comment can be removed once
157 157 //
158 158 // 6270645: Javadoc comments should be inherited from most derived
159 159 // superinterface or superclass
160 160 // is fixed.
161 161 /**
162 162 * Sets this Future to the result of its computation
163 163 * unless it has been cancelled.
164 164 */
165 165 public void run() {
166 166 sync.innerRun();
167 167 }
168 168
169 169 /**
170 170 * Executes the computation without setting its result, and then
171 171 * resets this Future to initial state, failing to do so if the
172 172 * computation encounters an exception or is cancelled. This is
173 173 * designed for use with tasks that intrinsically execute more
174 174 * than once.
175 175 * @return true if successfully run and reset
176 176 */
177 177 protected boolean runAndReset() {
178 178 return sync.innerRunAndReset();
179 179 }
180 180
181 181 /**
182 182 * Synchronization control for FutureTask. Note that this must be
183 183 * a non-static inner class in order to invoke the protected
184 184 * <tt>done</tt> method. For clarity, all inner class support
185 185 * methods are same as outer, prefixed with "inner".
186 186 *
187 187 * Uses AQS sync state to represent run status
188 188 */
189 189 private final class Sync extends AbstractQueuedSynchronizer {
190 190 private static final long serialVersionUID = -7828117401763700385L;
191 191
192 192 /** State value representing that task is ready to run */
193 193 private static final int READY = 0;
194 194 /** State value representing that task is running */
195 195 private static final int RUNNING = 1;
196 196 /** State value representing that task ran */
197 197 private static final int RAN = 2;
198 198 /** State value representing that task was cancelled */
199 199 private static final int CANCELLED = 4;
200 200
201 201 /** The underlying callable */
202 202 private final Callable<V> callable;
203 203 /** The result to return from get() */
204 204 private V result;
205 205 /** The exception to throw from get() */
206 206 private Throwable exception;
207 207
208 208 /**
209 209 * The thread running task. When nulled after set/cancel, this
210 210 * indicates that the results are accessible. Must be
211 211 * volatile, to ensure visibility upon completion.
212 212 */
213 213 private volatile Thread runner;
214 214
215 215 Sync(Callable<V> callable) {
216 216 this.callable = callable;
217 217 }
218 218
219 219 private boolean ranOrCancelled(int state) {
220 220 return (state & (RAN | CANCELLED)) != 0;
221 221 }
222 222
223 223 /**
224 224 * Implements AQS base acquire to succeed if ran or cancelled
225 225 */
226 226 protected int tryAcquireShared(int ignore) {
227 227 return innerIsDone() ? 1 : -1;
228 228 }
229 229
230 230 /**
231 231 * Implements AQS base release to always signal after setting
232 232 * final done status by nulling runner thread.
233 233 */
234 234 protected boolean tryReleaseShared(int ignore) {
235 235 runner = null;
236 236 return true;
237 237 }
238 238
239 239 boolean innerIsCancelled() {
240 240 return getState() == CANCELLED;
241 241 }
242 242
243 243 boolean innerIsDone() {
244 244 return ranOrCancelled(getState()) && runner == null;
245 245 }
246 246
247 247 V innerGet() throws InterruptedException, ExecutionException {
248 248 acquireSharedInterruptibly(0);
249 249 if (getState() == CANCELLED)
250 250 throw new CancellationException();
251 251 if (exception != null)
252 252 throw new ExecutionException(exception);
253 253 return result;
254 254 }
255 255
256 256 V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
257 257 if (!tryAcquireSharedNanos(0, nanosTimeout))
258 258 throw new TimeoutException();
259 259 if (getState() == CANCELLED)
260 260 throw new CancellationException();
261 261 if (exception != null)
262 262 throw new ExecutionException(exception);
263 263 return result;
264 264 }
265 265
266 266 void innerSet(V v) {
267 267 for (;;) {
268 268 int s = getState();
269 269 if (s == RAN)
270 270 return;
271 271 if (s == CANCELLED) {
272 272 // aggressively release to set runner to null,
273 273 // in case we are racing with a cancel request
274 274 // that will try to interrupt runner
275 275 releaseShared(0);
276 276 return;
277 277 }
278 278 if (compareAndSetState(s, RAN)) {
279 279 result = v;
280 280 releaseShared(0);
281 281 done();
282 282 return;
283 283 }
284 284 }
285 285 }
286 286
287 287 void innerSetException(Throwable t) {
288 288 for (;;) {
289 289 int s = getState();
290 290 if (s == RAN)
291 291 return;
292 292 if (s == CANCELLED) {
293 293 // aggressively release to set runner to null,
294 294 // in case we are racing with a cancel request
295 295 // that will try to interrupt runner
296 296 releaseShared(0);
297 297 return;
298 298 }
299 299 if (compareAndSetState(s, RAN)) {
300 300 exception = t;
301 301 releaseShared(0);
302 302 done();
303 303 return;
304 304 }
305 305 }
306 306 }
307 307
308 308 boolean innerCancel(boolean mayInterruptIfRunning) {
309 309 for (;;) {
310 310 int s = getState();
311 311 if (ranOrCancelled(s))
312 312 return false;
313 313 if (compareAndSetState(s, CANCELLED))
314 314 break;
315 315 }
316 316 if (mayInterruptIfRunning) {
317 317 Thread r = runner;
318 318 if (r != null)
319 319 r.interrupt();
320 320 }
321 321 releaseShared(0);
322 322 done();
323 323 return true;
324 324 }
325 325
326 326 void innerRun() {
327 327 if (!compareAndSetState(READY, RUNNING))
328 328 return;
329 329
330 330 runner = Thread.currentThread();
331 331 if (getState() == RUNNING) { // recheck after setting thread
332 332 V result;
333 333 try {
334 334 result = callable.call();
335 335 } catch (Throwable ex) {
336 336 setException(ex);
337 337 return;
338 338 }
339 339 set(result);
340 340 } else {
341 341 releaseShared(0); // cancel
342 342 }
343 343 }
344 344
345 345 boolean innerRunAndReset() {
346 346 if (!compareAndSetState(READY, RUNNING))
347 347 return false;
348 348 try {
349 349 runner = Thread.currentThread();
350 350 if (getState() == RUNNING)
351 351 callable.call(); // don't set result
352 352 runner = null;
353 353 return compareAndSetState(RUNNING, READY);
354 354 } catch (Throwable ex) {
355 355 setException(ex);
356 356 return false;
357 357 }
358 358 }
359 359 }
360 360 }
↓ open down ↓ |
262 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX