工程造價(jià)材料信息網(wǎng)山東seo推廣
文章目錄
- 1.介紹
- 2.使用示例
- 3.執(zhí)行過(guò)程描述
- 4.整體的關(guān)系
- 5.涉及到的核心源碼(只提取了關(guān)鍵代碼)
- 5.1 Callable
- 5.2 RunnableFuture
- 5.3 FutureTask
- 5.4 Thread
1.介紹
FutureTask 能夠接收 Callable 類(lèi)型的參數(shù),用來(lái)處理有返回結(jié)果的情況。
2.使用示例
// 創(chuàng)建任務(wù)對(duì)象
FutureTask<Integer> task = new FutureTask<>(() -> {log.debug("running");Thread.sleep(1000);return 200;
});new Thread(task).start();// 主線程阻塞,同步等待 task 執(zhí)行完畢的結(jié)果
Integer value = task.get();System.out.println("value = " + value);
3.執(zhí)行過(guò)程描述
- FutureTask 類(lèi)在實(shí)例化構(gòu)造時(shí)需要傳入一個(gè)實(shí)現(xiàn)了 Callable 接口的類(lèi),實(shí)現(xiàn) Callable 接口需要重寫(xiě) call 方法,該方法需要一個(gè)返回值,由于 Callable 定義時(shí)是以泛型定義返回值,因此我們可以自定義返回值。FutureTask 會(huì)將傳入的這個(gè) Callable 實(shí)現(xiàn)類(lèi)賦給自己的屬性
private Callable<V> callable;
- FutureTask 間接實(shí)現(xiàn)了 Runnable 接口,并重寫(xiě)了 run 方法,重寫(xiě)的 run 方法中會(huì)調(diào)用到 屬性 callable 的 call 方法,并將 call 方法返回值存儲(chǔ)到自己的屬性
private Object outcome;
- Thread 類(lèi)在實(shí)例化構(gòu)造時(shí)可以傳入一個(gè) Runnable 接口的類(lèi),由于 FutureTask 實(shí)現(xiàn)了 Runnable 接口,因此我們可以直接將 FutureTask 對(duì)象作為構(gòu)造器實(shí)參賦給 Thread對(duì)象的屬性
private Runnable target;
- Thread 對(duì)象調(diào)用 start 方法,最終會(huì)調(diào)用到自身就重寫(xiě)了的 run 方法,自身重寫(xiě)的 run 方法中又會(huì)調(diào)用到 target 的 run 方法,即 FutureTask 自身已經(jīng)重寫(xiě)的 run 方法,這時(shí)候就可以回到“第 2 點(diǎn)講解”,了解到 FutureTask 的 run 方法中所做的事情。
- FutureTask 對(duì)象的 get() 方法,是去獲取 callable 的 call 方法返回值,即屬性 outcome 的值。get 方法中會(huì)調(diào)用 awaitDone 方法,awaitDone 方法中會(huì)使用
for (;;)
造成當(dāng)前線程阻塞,直到 call 方法執(zhí)行結(jié)束可以獲取到 outcome 的值,并將 outcome 作為 get() 方法返回值。
4.整體的關(guān)系
Thread 和 FutureTask 類(lèi)均實(shí)現(xiàn)了 Runnable 接口并重寫(xiě)了其 run 方法,Thread 將 FutureTask 進(jìn)行聚合賦給 private Runnable target
。
5.涉及到的核心源碼(只提取了關(guān)鍵代碼)
5.1 Callable
@FunctionalInterface
public interface Callable<V> {/*** Computes a result, or throws an exception if unable to do so.** @return computed result* @throws Exception if unable to compute a result*/V call() throws Exception;
}
5.2 RunnableFuture
public interface RunnableFuture<V> extends Runnable, Future<V> {/*** Sets this Future to the result of its computation* unless it has been cancelled.*/void run();
}
5.3 FutureTask
public class FutureTask<V> implements RunnableFuture<V> {/** The underlying callable; nulled out after running */private Callable<V> callable;// 存儲(chǔ) callable 接口的 call 方法的返回值/** The result to return or exception to throw from get() */private Object outcome; // non-volatile, protected by state reads/writes/*() -> {log.debug("running");Thread.sleep(1000);return 200;}這實(shí)際上是對(duì)函數(shù)式接口 callable 的 V call() 方法進(jìn)行實(shí)現(xiàn)*/public FutureTask(Callable<V> callable) {if (callable == null)throw new NullPointerException();this.callable = callable;this.state = NEW; // ensure visibility of callable} public void run() {// ...Callable<V> c = callable;// 重寫(xiě)了 Runnable 函數(shù)式接口的 run 方法result = c.call();// ...// 賦值set(result);// ...}protected void set(V v) {if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {// 將 callable 的 call 方法返回值,即我們自定義的 200 賦給 outcomeoutcome = v;UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final statefinishCompletion();}}// 獲取 callable 的 call 方法的返回結(jié)果public V get() throws InterruptedException, ExecutionException {int s = state;if (s <= COMPLETING)// 獲取到結(jié)果成功的標(biāo)識(shí),實(shí)際是在 awaitDone 方法中用了死循環(huán)不斷判斷是否生成返回結(jié)果,造成了線程阻塞s = awaitDone(false, 0L);// 獲取結(jié)果return report(s);}// timed-是否計(jì)時(shí)等待,即是否設(shè)置等待超時(shí),false表示不設(shè)置,true表示設(shè)置private int awaitDone(boolean timed, long nanos)throws InterruptedException {final long deadline = timed ? System.nanoTime() + nanos : 0L;WaitNode q = null;boolean queued = false;// 死循環(huán)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 yetThread.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);}elseLockSupport.park(this);}}
}
5.4 Thread
public class Thread implements Runnable {/* What will be run. */private Runnable target;// 構(gòu)造器,將間接實(shí)現(xiàn)了 Runnable 接口的 FutureTask 對(duì)象傳進(jìn)來(lái)public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}private void init(ThreadGroup g, Runnable target, String name, long stackSize) {init(g, target, name, stackSize, null, true);}private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {// ...// 將 FutureTask 對(duì)象賦給 Thread 對(duì)象的屬性 targetthis.target = target;}@Overridepublic void run() {if (target != null) {// 實(shí)際調(diào)用的 FutureTask 對(duì)象重寫(xiě)的 run 方法,重寫(xiě)的 run 方法中又會(huì)調(diào)用 callable 接口的 call 方法,并將 call 方法的返回值賦給 FutureTask 對(duì)象的屬性 outcometarget.run();}}
}