同步調用,異步回調和 Future 模式
阿新 • • 發佈:2018-02-28
同步 異步 任務調度 FutureTask 目標
通過與方法的同步調用,異步回調比較,理解 Future 模式
三者的不同
讓我們先來明確一下同步與異步的不同。我們這裏所說的同步和異步,僅局限在方法的同步調用和異步回調中。即,同步指的是調用一個方法,調用方要等待該方法所執行的任務完全執行完畢,然後控制權回到調用方;異步指的是調用一個方法,調用方不等該方法執行的任務完畢就返回,當任務執行完畢時會自動執行調用方傳入的一塊代碼。
同步調用
void runTask {
doTask1()
doTask2()
}
同步調用,執行完 doTask1 在執行 doTask2
異步回調
doTask1(new Callback() { void call() { doTask3() } }); doTask2();
異步回調,會同時執行 doTask1 和 doTask2, 在執行完 doTask1 後執行 doTask3
Future 模式
Future future = doTask1();
doTask2();
doTask3();
Result result = future.get();
我們可以看到,Future 模式中,一個任務的啟動和獲取結果分成了兩部分,啟動執行是異步的,調用後立馬返回,調用者可以繼續做其他的任務,而等到其他任務做完,再獲取Future的結果,此時調用 get 時是同步的,也就是說如果 doTask1 如果還沒有做完,等它做完。
適用情景
我們根據前面的例子可以看出,同步調用適合執行耗時短的任務,異步回調適合執行耗時長的任務,而且調用它之後調用的任務沒什麽關系。
Future 則適合執行長得任務,而且它的結果可能與調用後執行的任務有關系。比如,在燒水的過程中洗刷水壺,最後兩者都完了才能泡茶。
Future模式的 Java 實現
Java 的並發庫實現了 Future 模式,它定義了 Future 接口:
public interface Future<V> { boolean cancel(boolean var1); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long var1, TimeUnit var3) throws InterruptedException, ExecutionException, TimeoutException; }
它未來將會產生我們所需要的結果。
我們通過它取消任務的執行,判斷是否取消和是否完成,獲取結果。
Java 庫還實現了一個 FutureTask, 它實現了 RunnableFuture(它繼承了 Runnable 和 Future)。於是我們就可以用 Executor 來執行這個任務了。
FutureTask<String> futureTask = new FutureTask<>(new Runnable() {
@Override
public void run() {
}
}, "hello");
Executors.newSingleThreadExecutor().execute(futureTask);
... 其他任務
try {
String result = futureTask.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
總結
- 同步調用,調用方掌握控制權
- 異步回調,調用方放權,從而可以實現並行處理任務
- Future 模式,則是控制權和平行處理的折中
同步調用,異步回調和 Future 模式