摘要:所以很容易出現(xiàn)某一個商店的數(shù)據(jù)遲遲無法返回的情況。工廠方法接受由對象構成的數(shù)組數(shù)組中所有的完成后它返回一個對象。異步的可以通過進行合并,無論他們之間是否有依賴關系??梢詾樽砸粋€回調(diào)函數(shù),在執(zhí)行完畢時使用。
【最佳價格查詢器的優(yōu)化
由于我們的兩個遠程服務:1.查詢價格,2.查詢折扣價格都是基于網(wǎng)絡的。所以很容易出現(xiàn)某一個商店的數(shù)據(jù)遲遲無法返回的情況。由于這些原因,我希望查詢器在查詢時能夠?qū)⒛玫綌?shù)據(jù)先返回過來,而不是等待所有的異步查詢完成后集中返回一個List。
我們首要需要避免的就是:等待創(chuàng)建一個包含所有價格的List。我們應該直接處理CompletableFuture流,然后去響應他的completion事件,每一個CompletableFuture對象完成時獲取到相應的返回值。
先將Discount的折扣服務延遲時間修改為隨機值:
//計算折扣價格 private static Double apply(double price ,Code code){ //模擬遠程操作的延遲 delay(); return (price * (100 - code.percantage)) / 100; } private static void delay(){ try { //隨機延遲時間 int delay = 500 + random.nextInt(2000); Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } }
開始實現(xiàn)最佳價格查詢器:
package BestPriceFinder; import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.stream.Collectors; import java.util.stream.Stream; /** * 最佳價格查詢器 */ public class BestFinder { Listshops = Arrays.asList( new Shop("A"), new Shop("B"), new Shop("C"), new Shop("D"), new Shop("E"), new Shop("F"), new Shop("G"), new Shop("H"), new Shop("I"), new Shop("J") ); public void findPricesContinue(String product){ long st = System.currentTimeMillis(); Stream > futurePrices = shops.stream() //首先異步獲取價格 .map(shop -> CompletableFuture.supplyAsync(() -> shop.getPriceFormat(product),myExecutor)) //將獲取的字符串解析成對象 .map(future -> future.thenApply(Quote::parse)) //使用另一個異步任務有獲取折扣價格 .map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote),myExecutor))); //thenAccept()會在CompletableFuture完成之后使用他的返回值,這里會持續(xù)執(zhí)行子線程 CompletableFuture[] futures = futurePrices.map(f -> f.thenAccept(s -> { String sout = String.format("%s done in %s mesc",s,(System.currentTimeMillis() - st)); System.out.println(sout); })) .toArray(size -> new CompletableFuture[size]); //allOf()工廠方法接受由CompletableFuture對象構成的數(shù)組,這里使用其等待所有的子線程執(zhí)行完畢 CompletableFuture.allOf(futures).join(); } /** * 異步查詢 * 相比并行流的話CompletableFuture更有優(yōu)勢:可以對執(zhí)行器配置,設置線程池大小 */ @SuppressWarnings("all") private final Executor myExecutor = Executors.newFixedThreadPool(Math.min(shops.size(), 100), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); //使用守護線程保證不會阻止程序的關停 t.setDaemon(true); return t; } });
thenAccept():提供了在CompletableFuture對象完成后使用他的返回值的功能。這樣我們的每一個CompletableFuture完成后就會打印他的返回值,最終等待所有的子線程完畢。
allOf():工廠方法接受由CompletableFuture對象構成的數(shù)組,數(shù)組中所有的CompletableFuture完成后它返回一個CompletableFuture
anyOf():廠方法接受由CompletableFuture對象構成的數(shù)組,返回數(shù)組中第一個完成的CompletableFuture的返回值CompletableFuture
【小結(jié)執(zhí)行耗時的操作,尤其是依賴了遠程服務的操作,應該使用異步任務提高效率。
盡可能的提供異步API,使用CompletableFuture類提供的特性可以輕松實現(xiàn)。
CompletableFuture類提供了異常機制,可以管理與拋出異步任務中執(zhí)行的異常。
同步的API封裝到CompletableFuture中可以以異步方式使用其結(jié)果。
異步的API可以通過CompletableFuture進行合并,無論他們之間是否有依賴關系。
可以為CompletableFuture注冊一個回調(diào)函數(shù),在執(zhí)行完畢時使用。
可以決定什么時候結(jié)束運行,是所有的CompletableFuture結(jié)束后,還是第一個CompletableFuture結(jié)束時就完成。
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68258.html
摘要:線程封閉當訪問共享的可變數(shù)據(jù)時,通常需要使用同步。如果僅在單線程內(nèi)訪問數(shù)據(jù),就不要同步。這種技術成為線程封閉。棧封閉棧封閉是線程封閉的一種特例,在棧封閉中,只能通過局部變量才能訪問對象。,對象是正確創(chuàng)建的。 線程封閉 當訪問共享的可變數(shù)據(jù)時,通常需要使用同步。一種避免使用同步的方式就是不共享數(shù)據(jù)。如果僅在單線程內(nèi)訪問數(shù)據(jù),就不要同步。這種技術成為線程封閉(Thread Confine...
摘要:大家好,我是冰河有句話叫做投資啥都不如投資自己的回報率高。馬上就十一國慶假期了,給小伙伴們分享下,從小白程序員到大廠高級技術專家我看過哪些技術類書籍。 大家好,我是...
摘要:三關鍵字能保證原子性嗎并發(fā)編程藝術這本書上說保證但是在自增操作非原子操作上不保證,多線程編程核心藝術這本書說不保證。多線程訪問關鍵字不會發(fā)生阻塞,而關鍵字可能會發(fā)生阻塞關鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)synchroniz...
摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點,其中有一項就是,其上下文切換和模式切換的時間消耗非常少。因為多線程競爭鎖時會引起上下文切換。減少線程的使用。很多編程語言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時至關重要。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Java多線程學習(二)synchronized關鍵字(1) java多線程學習(二)syn...
摘要:因為多線程競爭鎖時會引起上下文切換。減少線程的使用。舉個例子如果說服務器的帶寬只有,某個資源的下載速度是,系統(tǒng)啟動個線程下載該資源并不會導致下載速度編程,所以在并發(fā)編程時,需要考慮這些資源的限制。 最近私下做一項目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學習(一)Java多線程入門 Jav...
閱讀 2762·2021-11-19 09:40
閱讀 5345·2021-09-27 14:10
閱讀 2114·2021-09-04 16:45
閱讀 1491·2021-07-25 21:37
閱讀 3009·2019-08-30 10:57
閱讀 2992·2019-08-28 17:59
閱讀 1064·2019-08-26 13:46
閱讀 1418·2019-08-26 13:27