// a result that can be returned asynchronously //It implements both Future and Runnable // first look at the constructor public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable } //Run the runnable and return the given result public FutureTask(Runnable runnable, V result) { //The adapter mode converts the runnable interface this.callable = Executors.callable(runnable, result); this.state = NEW; // ensure visibility of callable } public static <T> Callable<T> callable(Runnable task, T result) { if (task == null) throw new NullPointerException(); return new RunnableAdapter<T>(task, result); } //The adapter mode converts the runnable interface static final class RunnableAdapter<T> implements Callable<T> { final Runnable task; final T result; RunnableAdapter(Runnable task, T result) { this.task = task; this.result = result; } public T call() { task.run(); return result; } } public void run() { //If state is not equal to 0 or the setting is currently occupied by other threads, return directly. if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return; try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } //If the set value has been executed if (ran) set(result); } } finally { runner = null; int s = state; //if cancelled if (s >= INTERRUPTING) // Give up execution rights handlePossibleCancellationInterrupt(s); } } //set the specified value protected void set(V v) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = v; UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state finishCompletion(); } } private void finishCompletion() { // release all waiting threads for (WaitNode q; (q = waiters) != null;) { // Clear the current thread successfully if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null; // release the thread LockSupport.unpark(t); } WaitNode next = q.next; if (next == null) break; q.next = null; // unlink to help gc q = next; } break; } } // hook method done(); callable = null; // to reduce footprint } private void handlePossibleCancellationInterrupt(int s) { if (s == INTERRUPTING) while (state == INTERRUPTING) Thread.yield(); // wait out pending interrupt } protected void done() { } // get the result public V get() throws InterruptedException, ExecutionException { int s = state; //if still done if (s <= COMPLETING) // block on this s = awaitDone(false, 0L); return report(s); } // join the queue to block the current thread private int awaitDone(boolean timed, long nanos) throws InterruptedException { final long deadline = timed? System.nanoTime () + nanos: 0L; WaitNode q = null; boolean queued = false; for (;;) { //if the current thread has been interrupted if (Thread.interrupted()) { // clear him from the waiting queue removeWaiter(q); throw new InterruptedException(); } int s = state; // already executed if (s > COMPLETING) { if (q != null) q.thread = null; return s; } else if (s == COMPLETING) // cannot time out yet // Give up execution rights Thread.yield(); else if (q == null) q = new WaitNode(); else if (!queued) // join the queue queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); else if (timed) { nanos = deadline - System.nanoTime (); //timeout delete q if (nanos <= 0L) { removeWaiter(q); return state; } // Suspend the current thread LockSupport.parkNanos(this, nanos); } else LockSupport.park(this); } } private void removeWaiter(WaitNode node) { if (node != null) { node.thread = null; retry: for (;;) { // restart on removeWaiter race for (WaitNode pred = null, q = waiters, s; q != null; q = s) { s = q.next; if (q.thread != null) pred = q; //It is explained here that q.thread==null, q is the node that needs to be deleted. else if (pred != null) { //Modify the next node of the previous node pred.next = s; //The previous node is deleted, and the cycle is repeated. if (pred.thread == null) continue retry; } //Go here to indicate that the first node is the deleted node else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s)) // set failure to recycle continue retry; } break; } } } //get value private V report(int s) throws ExecutionException { Object x = outcome; if (s == NORMAL) return (V)x; if (s >= CANCELLED) throw new CancellationException(); throw new ExecutionException((Throwable)x); } //Waiting for a result for a certain period of time will timeout and throw an exception public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { if (unit == null) throw new NullPointerException(); int s = state; if (s <= COMPLETING && (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING) throw new TimeoutException(); return report(s); } //whether the task is canceled public boolean isCancelled() { return state >= CANCELLED; } //Is the task completed public boolean isDone() { return state != NEW; } // Attempt to cancel the execution of the task public boolean cancel(boolean mayInterruptIfRunning) { //The task has started and returns false directly if (state != NEW) return false; // try to interrupt if (mayInterruptIfRunning) { if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING)) return false; Thread t = runner; if (t != null) t.interrupt(); UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state } // try to cancel else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED)) return false; finishCompletion(); return true; } // set result as exception protected void setException(Throwable t) { if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { outcome = t; UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state finishCompletion(); } } //Execute the calculation without setting the result and reset it after execution protected boolean runAndReset() { if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) return false; boolean ran = false; int s = state; try { Callable<V> c = callable; if (c != null && s == NEW) { try { c.call(); // don't set result ran = true; } catch (Throwable ex) { setException(ex); } } } finally { runner = null; s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } return ran && s == NEW; }
Read FutureTask source code
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=326480946&siteId=291194637
Recommended
Ranking