亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

java并發(fā)編程學(xué)習(xí)15--CompletableFuture(二)

VioletJack / 2438人閱讀

摘要:比如我們獲取價(jià)格的同時(shí)也獲取匯率遠(yuǎn)程獲取匯率方法獲取匯率結(jié)合倆個(gè)異步操作沃爾瑪接受兩個(gè)參數(shù)對(duì)象表明第二個(gè)異步操作接口兩個(gè)異步操作的結(jié)果合并處理

【模擬情景

上一篇說到每一個(gè)shop都會(huì)提供一個(gè)價(jià)格查詢的服務(wù),但是現(xiàn)在我們進(jìn)行假設(shè):

1. 所有的價(jià)格查詢是同步方式提供的
2. shop在返回價(jià)格的同時(shí)會(huì)返回一個(gè)折扣碼
3. 我們需要解析返回的字符串,并且根據(jù)折扣碼區(qū)獲取折扣后的價(jià)格
4. 折扣后的價(jià)格計(jì)算依然是同步執(zhí)行的
5. 查詢價(jià)格返回的字符串格式為shopName:price:discountCode("沃爾瑪:200:15")

定義商店對(duì)象:Shop.java

public class Shop {

    private String name;
    public Shop(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
   
    public String getPriceFormat(String product){
        double price = calculatePrice(product);
        //隨機(jī)返回一個(gè)折扣碼
        Discount.Code code = Discount.Code.values()[random.nextInt(Discount.Code.values().length)];
        return String.format("%s:%.2f:%s",name,price,code);
    }

    private double calculatePrice(String product){
        delay();
        return random.nextDouble() * product.charAt(0) + product.charAt(1);
    }

    private Random random = new Random();
    /**
     * 模擬耗時(shí)操作:延遲一秒
     */
    private static void delay(){
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

定義折扣對(duì)象:Discount.java

public class Discount {
    public enum Code{

        NONE(0),SILVER(5),GOLD(10),PLATINUM(15),DIAMOND(20);

        private final int percantage;
        Code(int percentage){
            this.percantage = percentage;
        }
    }

    public static String applyDiscount(Quote quote){
        return quote.getShopName() + "prices is " + Discount.apply(quote.getPrice(),quote.getDiscountCode());
    }
    //計(jì)算折扣價(jià)格
    private static Double apply(double price ,Code code){
        //模擬遠(yuǎn)程操作的延遲
        delay();
        return (price * (100 - code.percantage)) / 100;
    }
    private static void delay(){
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

用于封裝解析getPriceFormat的字符串對(duì)象:Quote.java

public class Quote {

    private final String shopName;
    private final double price;
    private final Discount.Code discountCode;

    public Quote(String shopName,double price,Discount.Code code){
        this.shopName = shopName;
        this.price = price;
        this.discountCode = code;
    }
    public static Quote parse(String s){
        String[] split = s.split(":");
        String shopName = split[0];
        Double price = Double.valueOf(split[1]);
        Discount.Code code = Discount.Code.valueOf(split[2]);
        return new Quote(shopName,price,code);
    }
    public double getPrice() {
        return price;
    }
    public String getShopName() {
        return shopName;
    }
    public Discount.Code getDiscountCode() {
        return discountCode;
    }
}

于是現(xiàn)在的任務(wù)就是:

1. 遠(yuǎn)程查詢商品價(jià)格
2. 將獲得的字符串解析成為Quote對(duì)象
3. 根據(jù)Quote對(duì)象遠(yuǎn)程獲取折扣后的價(jià)格

現(xiàn)在先看看同步的方式來執(zhí)行這個(gè)操作:

  public List findPrices2(String product){
        return shops.stream()
                .map(shop -> shop.getPriceFormat(product))
                .map(Quote::parse)
                .map(Discount::applyDiscount)
                .collect(Collectors.toList());
    }

因?yàn)橛袃蓚€(gè)耗時(shí)操作,每個(gè)1秒,耗時(shí)毫無疑問20秒以上:

【對(duì)多個(gè)異步任務(wù)進(jìn)行流水線操作

1. 獲取價(jià)格:使用CompletableFuture.supplyAsync()工廠方法即可,一旦運(yùn)行結(jié)束每個(gè)CompletableFuture對(duì)象會(huì)包含一個(gè)shop返回的字符串,這里記住使用我們自定義的執(zhí)行器。

2. 解析報(bào)價(jià):一般情況下解析操作并不涉及到IO處理,所可以采用同步處理,所以這里我們直接使用CompletableFuture對(duì)象的thenApply()方法,表明在的帶運(yùn)算結(jié)果后立刻同步處理。

3. 計(jì)算折扣價(jià)格:這是一個(gè)遠(yuǎn)程操作,肯定是需要異步執(zhí)行的,于是我們現(xiàn)在就有了兩次異步處理(1.獲取價(jià)格,2.計(jì)算折扣)?,F(xiàn)在使用級(jí)聯(lián)的方式將它們串聯(lián)起來工作。CompletableFuture提供了thenCompose方法,表明將兩個(gè)異步操作進(jìn)行流水線處理。第一個(gè)異步操作的結(jié)果會(huì)成為第二個(gè)異步操作的入?yún)?。使用這樣的方式,即使Future在向不同的shop手機(jī)報(bào)價(jià),主線程依然可以執(zhí)行其他操作,比如響應(yīng)UI事件。

于是我們有了如下代碼:

     /**
     * 異步查詢
     * 相比并行流的話CompletableFuture更有優(yōu)勢(shì):可以對(duì)執(zhí)行器配置,設(shè)置線程池大小
     */
    @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;
        }
    });

    public List findPrices2Async(String product){
       List> futurePrices = shops.stream()
                //首先異步獲取價(jià)格
                .map(shop -> CompletableFuture.supplyAsync(() -> shop.getPriceFormat(product),myExecutor))
                //將獲取的字符串解析成對(duì)象
                .map(future -> future.thenApply(Quote::parse))
                //使用另一個(gè)異步任務(wù)有獲取折扣價(jià)格
                .map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote),myExecutor)))
                .collect(Collectors.toList());
       //等待所有異步任務(wù)完成
       return futurePrices.stream().map(CompletableFuture::join).collect(Collectors.toList());

運(yùn)算結(jié)果不到3秒:

【整合兩個(gè)CompletableFuture對(duì)象

我們剛才使用thenCompose()將兩個(gè)CompletableFuture結(jié)合了起來,并且一個(gè)CompletableFuture的運(yùn)算結(jié)果將作為第二個(gè)CompletableFuture的入?yún)?。但是更多的情況是兩個(gè)不相干的CompletableFuture對(duì)象相互結(jié)合,并且我們也不希望第一個(gè)任務(wù)結(jié)束之后才開始第二個(gè)任務(wù)。這時(shí)可以使用thenCombine()。

比如我們獲取價(jià)格的同時(shí)也獲取匯率:

遠(yuǎn)程獲取匯率方法:

 /**
     * 獲取匯率
     */
    public double getRate(String type){
        delay();
        if("$".equals(type)){
            return 0.3;
        }
        if("¥".equals(type)){
            return 0.7;
        }
        return 1;
    }

結(jié)合倆個(gè)異步操作:

 @Test
    public void combine(){
        Shop shop = new Shop("沃爾瑪");
        Future futurePrice = CompletableFuture.supplyAsync(() -> shop.getPrice("iphoneX"))
                                                      .thenCombine(CompletableFuture.supplyAsync(() -> shop.getRate("$")),
                                                                   (price,rate) -> price * rate);
    }

thenCombine()接受兩個(gè)參數(shù):

1. CompletableFuture對(duì)象:表明第二個(gè)異步操作
2. BiFunction接口:兩個(gè)異步操作的結(jié)果合并處理


文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/68237.html

相關(guān)文章

  • Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題

    摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。很多編程語(yǔ)言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...

    dingding199389 評(píng)論0 收藏0
  • Java多線程學(xué)習(xí)(七)并發(fā)編程中一些問題

    摘要:因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。舉個(gè)例子如果說服務(wù)器的帶寬只有,某個(gè)資源的下載速度是,系統(tǒng)啟動(dòng)個(gè)線程下載該資源并不會(huì)導(dǎo)致下載速度編程,所以在并發(fā)編程時(shí),需要考慮這些資源的限制。 最近私下做一項(xiàng)目,一bug幾日未解決,總惶恐。一日頓悟,bug不可怕,怕的是項(xiàng)目不存在bug,與其懼怕,何不與其剛正面。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Jav...

    yimo 評(píng)論0 收藏0
  • Java多線程學(xué)習(xí)(三)volatile關(guān)鍵字

    摘要:三關(guān)鍵字能保證原子性嗎并發(fā)編程藝術(shù)這本書上說保證但是在自增操作非原子操作上不保證,多線程編程核心藝術(shù)這本書說不保證。多線程訪問關(guān)鍵字不會(huì)發(fā)生阻塞,而關(guān)鍵字可能會(huì)發(fā)生阻塞關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchroniz...

    tain335 評(píng)論0 收藏0
  • 我的阿里之路+Java面經(jīng)考點(diǎn)

    摘要:我的是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)。因?yàn)槲倚睦砗芮宄业哪繕?biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來的學(xué)習(xí)計(jì)劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...

    姘擱『 評(píng)論0 收藏0
  • 并發(fā)

    摘要:表示的是兩個(gè),當(dāng)其中任意一個(gè)計(jì)算完并發(fā)編程之是線程安全并且高效的,在并發(fā)編程中經(jīng)常可見它的使用,在開始分析它的高并發(fā)實(shí)現(xiàn)機(jī)制前,先講講廢話,看看它是如何被引入的。電商秒殺和搶購(gòu),是兩個(gè)比較典型的互聯(lián)網(wǎng)高并發(fā)場(chǎng)景。 干貨:深度剖析分布式搜索引擎設(shè)計(jì) 分布式,高可用,和機(jī)器學(xué)習(xí)一樣,最近幾年被提及得最多的名詞,聽名字多牛逼,來,我們一步一步來?yè)羝魄皟蓚€(gè)名詞,今天我們首先來說說分布式。 探究...

    supernavy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<