future模式:一種異步計算模式,並支持返回計算結果,在調用get()獲取到計算結果前能夠阻塞調用者線程異步
FutureTask是JDK針對與future模式的一種實現,它除了支持future特有的特色,還支持task的一些操做,好比取消,打斷。
一個FutureTask就是一個任務的計算單元,是調度的最小單位,它的調度藉助於JDK的Executor任務調度模型。須要開發人員建立好FutureTask對象後,並送入到Executor去等待調度this
具體的執行過程,像下面是一段FutureTask的僞碼描述線程
建立一個futureTask對象task 提交task到調度器executor等待調度 等待調度中... 若是此時currentThread調取執行結果task.get(),會有幾種狀況 if task 尚未被executor調度或正在執行中 阻塞當前線程,並加入到一個阻塞鏈表中waitNode else if task被其它Thread取消,並取消成功 或task處於打斷狀態 throw exception else if task執行完畢,返回執行結果,或執行存在異常,返回異常信息 若是此時有另一個線程調用task.get() 執行過程同上
注意
:executor在執行FutureTask前,會先判斷是否被取消,若是取消就不在執行,但執行後就不能夠在取消了設計
private volatile int state; private static final int NEW = 0; // 建立 private static final int COMPLETING = 1; // 完成 private static final int NORMAL = 2; // private static final int EXCEPTIONAL = 3; // invoke task 出現異常 private static final int CANCELLED = 4; // cancel task private static final int INTERRUPTING = 5; // interrupting task private static final int INTERRUPTED = 6;
建立futureTask只須要須要一個callable對象或runnable對象的參數,並在建立時設置狀態爲NEWcode
public FutureTask(Callable<V> callable) { if (callable == null) throw new NullPointerException(); this.callable = callable; this.state = NEW; // ensure visibility of callable }
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 (Thread.interrupted()) { removeWaiter(q); throw new InterruptedException(); } int s = state; if (s > COMPLETING) { if (q != null) q.thread = null; return s; } else if (s == COMPLETING) // cannot time out yet Thread.yield(); else if (q == null) q = new WaitNode(); else if (!queued) queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q); else if (timed) { nanos = deadline - System.nanoTime(); if (nanos <= 0L) { removeWaiter(q); return state; } LockSupport.parkNanos(this, nanos); } else LockSupport.park(this); } }
public void run() { 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 (ran) set(result); } } finally { // runner must be non-null until state is settled to // prevent concurrent calls to run() runner = null; // state must be re-read after nulling runner to prevent // leaked interrupts int s = state; if (s >= INTERRUPTING) handlePossibleCancellationInterrupt(s); } }