一. Future
JDK 5引入了Future模式。Future接口是Java多線程Future模式的實現(xiàn),在java.util.concurrent包中,可以來進行異步計算。
Future模式是多線程設(shè)計常用的一種設(shè)計模式。Future模式可以理解成:我有一個任務(wù),提交給了Future,F(xiàn)uture替我完成這個任務(wù)。期間我自己可以去做任何想做的事情。一段時間之后,我就便可以從Future那兒取出結(jié)果。
Future的接口很簡單,只有五個方法。

Future接口的方法介紹如下:
boolean cancel (boolean mayInterruptIfRunning) 取消任務(wù)的執(zhí)行。參數(shù)指定是否立即中斷任務(wù)執(zhí)行,或者等等任務(wù)結(jié)束
boolean isCancelled () 任務(wù)是否已經(jīng)取消,任務(wù)正常完成前將其取消,則返回 true
boolean isDone () 任務(wù)是否已經(jīng)完成。需要注意的是如果任務(wù)正常終止、異?;蛉∠紝⒎祷豻rue
V get () throws InterruptedException, ExecutionException? 等待任務(wù)執(zhí)行結(jié)束,然后獲得V類型的結(jié)果。InterruptedException 線程被中斷異常, ExecutionException任務(wù)執(zhí)行異常,如果任務(wù)被取消,還會拋出CancellationException
V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一樣,多了設(shè)置超時時間。參數(shù)timeout指定超時時間,uint指定時間的單位,在枚舉類TimeUnit中有相關(guān)的定義。如果計 算超時,將拋出TimeoutException
一般情況下,我們會結(jié)合Callable和Future一起使用,通過ExecutorService的submit方法執(zhí)行Callable,并返回Future。


比起future.get(),其實更推薦使用get (long timeout, TimeUnit unit) 方法,設(shè)置了超時時間可以防止程序無限制的等待future的結(jié)果。
二. CompletableFuture介紹
2.1 Future模式的缺點
Future雖然可以實現(xiàn)獲取異步執(zhí)行結(jié)果的需求,但是它沒有提供通知的機制,我們無法得知Future什么時候完成。
要么使用阻塞,在future.get()的地方等待future返回的結(jié)果,這時又變成同步操作。要么使用isDone()輪詢地判斷Future是否完成,這樣會耗費CPU的資源。
2.2 CompletableFuture介紹
Netty、Guava分別擴展了Java 的 Future 接口,方便異步編程。
Java 8新增的CompletableFuture類正是吸收了所有Google Guava中ListenableFuture和SettableFuture的特征,還提供了其它強大的功能,讓Java擁有了完整的非阻塞編程模型:Future、Promise 和 Callback(在Java8之前,只有無Callback 的Future)。
CompletableFuture能夠?qū)⒒卣{(diào)放到與任務(wù)不同的線程中執(zhí)行,也能將回調(diào)作為繼續(xù)執(zhí)行的同步函數(shù),在與任務(wù)相同的線程中執(zhí)行。它避免了傳統(tǒng)回調(diào)最大的問題,那就是能夠?qū)⒖刂屏鞣蛛x到不同的事件處理器中。
CompletableFuture彌補了Future模式的缺點。在異步的任務(wù)完成后,需要用其結(jié)果繼續(xù)操作時,無需等待??梢灾苯油ㄟ^thenAccept、thenApply、thenCompose等方式將前面異步處理的結(jié)果交給另外一個異步事件處理線程來處理。
三. CompletableFuture特性
3.1 CompletableFuture的靜態(tài)工廠方法

runAsync 和 supplyAsync 方法的區(qū)別是runAsync返回的CompletableFuture是沒有返回值的。

而supplyAsync返回的CompletableFuture是由返回值的,下面的代碼打印了future的返回值。
3.2 Completable

future.get()在等待執(zhí)行結(jié)果時,程序會一直block,如果此時調(diào)用complete(T t)會立即執(zhí)行。
可以看到future調(diào)用complete(T t)會立即執(zhí)行。但是complete(T t)只能調(diào)用一次,后續(xù)的重復調(diào)用會失效。
如果future已經(jīng)執(zhí)行完畢能夠返回結(jié)果,此時再調(diào)用complete(T t)則會無效。