future.get方法阻塞問題的解決,實現按照任務完成的先后順序獲取任務的結果


1、Future

Future模式是多線程設計常用的一種設計模式。Future模式可以理解成:我有一個任務,提交給了Future,Future替我完成這個任務。期間我自己可以去做任何想做的事情。一段時間之后,我就便可以從Future那兒取出結果。
Future提供了三種功能:
判斷任務是否完成
能夠中斷任務
能夠獲取任務執行的結果
向線程池中提交任務的submit方法不是阻塞方法,而Future.get方法是一個阻塞方法,當submit提交多個任務時,只有所有任務都完成后,才能使用get按照任務的提交順序得到返回結果,所以一般需要使用future.isDone先判斷任務是否全部執行完成,完成后再使用future.get得到結果。(也可以用get (long timeout, TimeUnit unit)方法可以設置超時時間,防止無限時間的等待)
三段式的編程:1.啟動多線程任務2.處理其他事3.收集多線程任務結果,Future雖然可以實現獲取異步執行結果的需求,但是它沒有提供通知的機制,要么使用阻塞,在future.get()的地方等待future返回的結果,這時又變成同步操作;要么使用isDone()輪詢地判斷Future是否完成,這樣會耗費CPU的資源
解決方法:CompletionService和CompletableFuture(按照任務完成的先后順序獲取任務的結果)

2、CompletionService是java1.8之前最好用的方法,

能夠實現按照任務完成的先后順序獲取任務的結果。

(圖片查看原文鏈接)

 

 

CompletionService方法可以通過completionService.take().get()方法獲取最快完成的線程的返回結果(若當前沒有線程執行完成則阻塞直到最快的線程執行結束),第二次調用則返回第二快完成的線程的返回結果。

3、CompletableFuture接口

所謂異步調用其實就是實現一個可無需等待被調函數的返回值而讓操作繼續運行的方法。簡單的講就是另啟一個線程來完成調用中的部分計算,使調用繼續運行或返回,而不需要等待計算結果。但調用者仍需要取線程的計算結果。

JDK1.5新增了Future接口,用於描述一個異步計算的結果。雖然 Future 以及相關使用方法提供了異步執行任務的能力,但是對於結果的獲取卻是很不方便,只能通過阻塞或者輪詢的方式得到任務的結果。

JDK1.8后提出了CompletableFuture接口實現了Future和CompletionStage兩個接口,CompletionStage可以看做是一個異步任務執行過程的抽象(CompletionStage代表異步計算過程中的某一個階段,一個階段完成以后可能會觸發另外一個階段,一個階段的計算執行可以是一個Function,Consumer或者Runnable。比如:

 

 

我們可以基於CompletableFuture創建任務和鏈式處理多個任務,並實現按照任務完成的先后順序獲取任務的結果。

(1)創建任務

##使用runAsync方法新建一個線程來運行Runnable對象(無返回值);

##使用supplyAysnc方法新建線程來運行Supplier<T>對象(有返回值);

##基於線程池創建

(2)任務的異步處理

不論Future.get()方法還是CompletableFuture.get()方法都是阻塞的,為了獲取任務的結果同時不阻塞當前線程的執行,我們可以使用CompletionStage提供的方法結合callback來實現任務的異步處理。

##whenComplete:是執行當前任務的線程執行繼續執行 whenComplete 的任務。
##whenCompleteAsync:把 whenCompleteAsync 這個任務繼續提交給線程池來進行執行,也就是並行執行。

##thenApply:當一個線程依賴另一個線程時,可以使用 thenApply 方法來把這兩個線程串行化

##thenAccept:thenAccept接收上一階段的輸出作為本階段的輸入,並消費處理,無返回結果。 

##thenRun:不關心前一階段的計算結果,因為它不需要輸入參數,進行消費處理,無返回結果。

## thenCombine:會把兩個 CompletionStage 的任務都執行完成后,把兩個任務的結果一塊交給 thenCombine 來處理。

## applyToEither :兩個CompletionStage,誰執行返回的結果快,我就用那個CompletionStage的結果進行下一步的轉化操作。

##acceptEither 方法:兩個CompletionStage,誰執行返回的結果快,我就用那個CompletionStage的結果進行下一步的消耗操作
在CompletableFuture接口中除了使用whenComplete還可以使用handle等方法能實現按照任務完成的先后順序獲取任務的結果。

 

 


————————————————
版權聲明:本文為CSDN博主「傅里葉、」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_34562093/article/details/90209520


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM