FutureTask.java revision 7365de1056414750d0a7d1fdd26025fd247f0d04
1/* 2 * Written by Doug Lea with assistance from members of JCP JSR-166 3 * Expert Group and released to the public domain, as explained at 4 * http://creativecommons.org/licenses/publicdomain 5 */ 6 7package java.util.concurrent; 8 9import java.util.concurrent.locks.AbstractQueuedSynchronizer; 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 */ 34public class FutureTask<V> implements RunnableFuture<V> { 35 /** Synchronization control for FutureTask */ 36 private final Sync sync; 37 38 /** 39 * Creates a <tt>FutureTask</tt> that will, upon running, execute the 40 * given <tt>Callable</tt>. 41 * 42 * @param callable the callable task 43 * @throws NullPointerException if callable is null 44 */ 45 public FutureTask(Callable<V> callable) { 46 if (callable == null) 47 throw new NullPointerException(); 48 sync = new Sync(callable); 49 } 50 51 /** 52 * Creates a <tt>FutureTask</tt> that will, upon running, execute the 53 * given <tt>Runnable</tt>, and arrange that <tt>get</tt> will return the 54 * given result on successful completion. 55 * 56 * @param runnable the runnable task 57 * @param result the result to return on successful completion. If 58 * you don't need a particular result, consider using 59 * constructions of the form: 60 * <tt>Future<?> f = new FutureTask<Object>(runnable, null)</tt> 61 * @throws NullPointerException if runnable is null 62 */ 63 public FutureTask(Runnable runnable, V result) { 64 sync = new Sync(Executors.callable(runnable, result)); 65 } 66 67 public boolean isCancelled() { 68 return sync.innerIsCancelled(); 69 } 70 71 public boolean isDone() { 72 return sync.innerIsDone(); 73 } 74 75 public boolean cancel(boolean mayInterruptIfRunning) { 76 return sync.innerCancel(mayInterruptIfRunning); 77 } 78 79 /** 80 * @throws CancellationException {@inheritDoc} 81 */ 82 public V get() throws InterruptedException, ExecutionException { 83 return sync.innerGet(); 84 } 85 86 /** 87 * @throws CancellationException {@inheritDoc} 88 */ 89 public V get(long timeout, TimeUnit unit) 90 throws InterruptedException, ExecutionException, TimeoutException { 91 return sync.innerGet(unit.toNanos(timeout)); 92 } 93 94 /** 95 * Protected method invoked when this task transitions to state 96 * <tt>isDone</tt> (whether normally or via cancellation). The 97 * default implementation does nothing. Subclasses may override 98 * this method to invoke completion callbacks or perform 99 * bookkeeping. Note that you can query status inside the 100 * implementation of this method to determine whether this task 101 * has been cancelled. 102 */ 103 protected void done() { } 104 105 /** 106 * Sets the result of this Future to the given value unless 107 * this future has already been set or has been cancelled. 108 * This method is invoked internally by the <tt>run</tt> method 109 * upon successful completion of the computation. 110 * @param v the value 111 */ 112 protected void set(V v) { 113 sync.innerSet(v); 114 } 115 116 /** 117 * Causes this future to report an <tt>ExecutionException</tt> 118 * with the given throwable as its cause, unless this Future has 119 * already been set or has been cancelled. 120 * This method is invoked internally by the <tt>run</tt> method 121 * upon failure of the computation. 122 * @param t the cause of failure 123 */ 124 protected void setException(Throwable t) { 125 sync.innerSetException(t); 126 } 127 128 // The following (duplicated) doc comment can be removed once 129 // 130 // 6270645: Javadoc comments should be inherited from most derived 131 // superinterface or superclass 132 // is fixed. 133 /** 134 * Sets this Future to the result of its computation 135 * unless it has been cancelled. 136 */ 137 public void run() { 138 sync.innerRun(); 139 } 140 141 /** 142 * Executes the computation without setting its result, and then 143 * resets this Future to initial state, failing to do so if the 144 * computation encounters an exception or is cancelled. This is 145 * designed for use with tasks that intrinsically execute more 146 * than once. 147 * @return true if successfully run and reset 148 */ 149 protected boolean runAndReset() { 150 return sync.innerRunAndReset(); 151 } 152 153 /** 154 * Synchronization control for FutureTask. Note that this must be 155 * a non-static inner class in order to invoke the protected 156 * <tt>done</tt> method. For clarity, all inner class support 157 * methods are same as outer, prefixed with "inner". 158 * 159 * Uses AQS sync state to represent run status 160 */ 161 private final class Sync extends AbstractQueuedSynchronizer { 162 private static final long serialVersionUID = -7828117401763700385L; 163 164 /** State value representing that task is ready to run */ 165 private static final int READY = 0; 166 /** State value representing that task is running */ 167 private static final int RUNNING = 1; 168 /** State value representing that task ran */ 169 private static final int RAN = 2; 170 /** State value representing that task was cancelled */ 171 private static final int CANCELLED = 4; 172 173 /** The underlying callable */ 174 private final Callable<V> callable; 175 /** The result to return from get() */ 176 private V result; 177 /** The exception to throw from get() */ 178 private Throwable exception; 179 180 /** 181 * The thread running task. When nulled after set/cancel, this 182 * indicates that the results are accessible. Must be 183 * volatile, to ensure visibility upon completion. 184 */ 185 private volatile Thread runner; 186 187 Sync(Callable<V> callable) { 188 this.callable = callable; 189 } 190 191 private boolean ranOrCancelled(int state) { 192 return (state & (RAN | CANCELLED)) != 0; 193 } 194 195 /** 196 * Implements AQS base acquire to succeed if ran or cancelled 197 */ 198 protected int tryAcquireShared(int ignore) { 199 return innerIsDone() ? 1 : -1; 200 } 201 202 /** 203 * Implements AQS base release to always signal after setting 204 * final done status by nulling runner thread. 205 */ 206 protected boolean tryReleaseShared(int ignore) { 207 runner = null; 208 return true; 209 } 210 211 boolean innerIsCancelled() { 212 return getState() == CANCELLED; 213 } 214 215 boolean innerIsDone() { 216 return ranOrCancelled(getState()) && runner == null; 217 } 218 219 V innerGet() throws InterruptedException, ExecutionException { 220 acquireSharedInterruptibly(0); 221 if (getState() == CANCELLED) 222 throw new CancellationException(); 223 if (exception != null) 224 throw new ExecutionException(exception); 225 return result; 226 } 227 228 V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException { 229 if (!tryAcquireSharedNanos(0, nanosTimeout)) 230 throw new TimeoutException(); 231 if (getState() == CANCELLED) 232 throw new CancellationException(); 233 if (exception != null) 234 throw new ExecutionException(exception); 235 return result; 236 } 237 238 void innerSet(V v) { 239 for (;;) { 240 int s = getState(); 241 if (s == RAN) 242 return; 243 if (s == CANCELLED) { 244 // aggressively release to set runner to null, 245 // in case we are racing with a cancel request 246 // that will try to interrupt runner 247 releaseShared(0); 248 return; 249 } 250 if (compareAndSetState(s, RAN)) { 251 result = v; 252 releaseShared(0); 253 done(); 254 return; 255 } 256 } 257 } 258 259 void innerSetException(Throwable t) { 260 for (;;) { 261 int s = getState(); 262 if (s == RAN) 263 return; 264 if (s == CANCELLED) { 265 // aggressively release to set runner to null, 266 // in case we are racing with a cancel request 267 // that will try to interrupt runner 268 releaseShared(0); 269 return; 270 } 271 if (compareAndSetState(s, RAN)) { 272 exception = t; 273 releaseShared(0); 274 done(); 275 return; 276 } 277 } 278 } 279 280 boolean innerCancel(boolean mayInterruptIfRunning) { 281 for (;;) { 282 int s = getState(); 283 if (ranOrCancelled(s)) 284 return false; 285 if (compareAndSetState(s, CANCELLED)) 286 break; 287 } 288 if (mayInterruptIfRunning) { 289 Thread r = runner; 290 if (r != null) 291 r.interrupt(); 292 } 293 releaseShared(0); 294 done(); 295 return true; 296 } 297 298 void innerRun() { 299 if (!compareAndSetState(READY, RUNNING)) 300 return; 301 302 runner = Thread.currentThread(); 303 if (getState() == RUNNING) { // recheck after setting thread 304 V result; 305 try { 306 result = callable.call(); 307 } catch (Throwable ex) { 308 setException(ex); 309 return; 310 } 311 set(result); 312 } else { 313 releaseShared(0); // cancel 314 } 315 } 316 317 boolean innerRunAndReset() { 318 if (!compareAndSetState(READY, RUNNING)) 319 return false; 320 try { 321 runner = Thread.currentThread(); 322 if (getState() == RUNNING) 323 callable.call(); // don't set result 324 runner = null; 325 return compareAndSetState(RUNNING, READY); 326 } catch (Throwable ex) { 327 setException(ex); 328 return false; 329 } 330 } 331 } 332} 333