一. Future
JDK 5引入了Future模式。Future接口是Java多線程Future模式的實(shí)現(xiàn)谓晌,在java.util.concurrent包中,可以來進(jìn)行異步計算癞揉。
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ù)正常終止案铺、異呈呓妫或取消梆靖,都將返回true
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()谊迄,其實(shí)更推薦使用get (long timeout, TimeUnit unit) 方法闷供,設(shè)置了超時時間可以防止程序無限制的等待future的結(jié)果。
二. CompletableFuture介紹
2.1 Future模式的缺點(diǎn)
Future雖然可以實(shí)現(xiàn)獲取異步執(zhí)行結(jié)果的需求统诺,但是它沒有提供通知的機(jī)制歪脏,我們無法得知Future什么時候完成。
要么使用阻塞粮呢,在future.get()的地方等待future返回的結(jié)果婿失,這時又變成同步操作。要么使用isDone()輪詢地判斷Future是否完成啄寡,這樣會耗費(fèi)CPU的資源移怯。
2.2 CompletableFuture介紹
Netty、Guava分別擴(kuò)展了Java 的 Future 接口这难,方便異步編程舟误。
Java 8新增的CompletableFuture類正是吸收了所有Google Guava中ListenableFuture和SettableFuture的特征,還提供了其它強(qiáng)大的功能姻乓,讓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彌補(bǔ)了Future模式的缺點(diǎn)。在異步的任務(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ù)的重復(fù)調(diào)用會失效侄榴。
如果future已經(jīng)執(zhí)行完畢能夠返回結(jié)果雹锣,此時再調(diào)用complete(T t)則會無效。