背景介紹
想象這樣一個場景:你可能但願爲你的法國客戶提供指定主題的熱點報道。爲實現這一功能,你須要向 谷歌或者Twitter的API請求全部語言中針對該主題最熱門的評論,可能還須要依據你的內部算法 對它們的相關性進行排序。以後,你可能還須要使用谷歌的翻譯服務把它們翻譯成法語,甚至 利用谷歌地圖服務定位出評論做者的位置信息,最終將全部這些信息彙集起來,呈如今你的網站上。算法
典型的「混聚」式應用數據庫
在這種「混聚」應用式的應用中,咱們的應用可能會有如下兩種需求:編程
因爲咱們調用的許多都是外部提供的接口,極有可能出現因爲某些外部網絡服務發生響應慢的狀況。在這種狀況下,咱們可能但願依舊能爲用戶提供部分信息,好比提供帶問號標記的通用地圖,以文本的方式顯示信息,而不是呆呆地顯示一片空白屏幕,直到地圖服務器返回結果或者超時退出。服務器
要實現相似的服務,你須要與互聯網上的多個Web服務通訊。但是,你並不但願由於等待某 些服務的響應,阻塞應用程序的運行,浪費數十億寶貴的CPU時鐘週期。好比,不要由於等待 Facebook的數據,暫停對來自Twitter的數據處理。網絡
以上兩種場景體現了多任務程序設計的另外一面。若是你的主要目標是在同一個CPU上執 行幾個鬆耦合的任務,充分利用CPU的核,讓其足夠忙碌,從而最大化程序的吞吐量,那麼你其實真正想作的是避免由於等待遠程服務的返回,或者對數據庫的查詢,而阻塞線程的執行, 浪費寶貴的計算資源,由於這種等待的時間極可能至關長。這時就須要用到異步處理,在Java 5中提供的Future接口和在Java 8 中的新版實現CompletableFuture,就是處理這種狀況的利器。併發
Feature接口
Future接口在Java 5中被引入,設計初衷是對未來某個時刻會發生的結果進行建模。它建模 了一種異步計算,返回一個執行運算結果的引用,當運算結束後,這個引用被返回給調用方。在 Future中觸發那些潛在耗時的操做把調用線程解放出來,讓它能繼續執行其餘有價值的工做, 再也不須要呆呆等待耗時的操做完成。異步
Feature接口和Tread的區別
Future的優勢是它比 更底層的Thread更易用。要使用Future,一般你只須要將耗時的操做封裝在一個Callable對 象中,再將它提交給ExecutorService,就萬事大吉了。網站
Feature接口示例
下面是一個Feature的demo示例:.net
public void testFeature() {
//建立Executor- Service,通 過它你能夠 向線程池提 交任務
ExecutorService executor = Executors.newCachedThreadPool();
//向Executor- Service提交一個 Callable對象
final Future<Double> futureRate = executor.submit(new Callable<Double>() {
public Double call() {
//以異步方式在新的線程中執行耗時的操做
return doSomeLongComputation();
}
});
//異步操做進行的同時你能夠作其餘的事情
doSomethingElse();線程
try {
//獲取異步操做的結果,若是最終被阻塞,沒法獲得結果,那麼在最多等待1秒鐘以後退出
Double result = future.get(1, TimeUnit.SECONDS);
} catch (ExecutionException e) {
// 計算拋出一個異常
e.printStackTrace();
} catch (InterruptedException ie) { // 當前線程在等待過程當中被中斷
} catch (TimeoutException te) { // 在Future對象完成以前超過已過時
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
使用Future以異步方式執行長時間的操做
如上圖所示,這種編程方式讓你的線程能夠在ExecutorService以併發方式調 用另外一個線程執行耗時操做的同時,去執行一些其餘的任務。接着,若是你已經運行到沒有異步 操做的結果就沒法繼續任何有意義的工做時,能夠調用它的get方法去獲取操做的結果。若是操 做已經完成,該方法會馬上返回操做的結果,不然它會阻塞你的線程,直到操做完成,返回相應 的結果。若是該長時間運行的操做永遠不返回了會怎樣?爲了處理這種可能性,雖然Future提供了一個無需任何參數的get方法,咱們仍是推薦你們使用重 載版本的get方法,它接受一個超時的參數,經過它,你能夠定義你的線程等待Future結果的最 長時間,從而無需永無止境的等待下去。
Feature接口的侷限性
雖然Feature接口提供了方法來檢測異步計算是否已經結束(使用 isDone方法),等待異步操做結束,以及獲取計算的結果。可是這些特性還不足以讓你編寫簡潔的併發代碼。
咱們可能還須要更多的特性來幫助咱們寫出更好異步代碼,如:
將兩個異步計算合併爲一個——這兩個異步計算之間相互獨立,同時第二個又依賴於第 一個的結果。
等待Future集合中的全部任務都完成。
僅等待Future集合中最快結束的任務完成(有可能由於它們試圖經過不一樣的方式計算同一個值),並返回它的結果。
經過編程方式完成一個Future任務的執行(即以手工設定異步操做結果的方式)。
應對Future的完成事件(即當Future的完成事件發生時會收到通知,並能使用Future
計算的結果進行下一步的操做,不僅是簡單地阻塞等待操做的結果)。
下一節咱們將介紹新的CompletableFuture類(它實現了Future接口)如何利用Java 8 的新特性以更直觀的方式將上述需求都變爲可能。————————————————版權聲明:本文爲CSDN博主「棟先生」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。原文連接:https://blog.csdn.net/wangdong5678999/article/details/81837387