Java 8新特性之CompletableFuture:组合式异步编程(5)

顺序执行4个商品是4秒,然后又调用了Discount服务又4秒 所以是8秒。 虽然我们现在把流转换为并行流 性能会很好 但是数量大于8时也很慢。相反,使用自定义CompletableFuture执行器能够更充分的利用CPU资源。

List<CompletableFuture<String>> priceFutures = shops.stream()
                //异步获取每个shop中的价格
                .map(shop -> CompletableFuture.supplyAsync(
                        () -> shop.getPrice("hhhhh", executor)
                ))
                //Quote对象存在时,对其返回值进行转换
                .map(future -> future.thenApply(Quote::parse))
                //使用另一个异步任务构造期望的future,申请折扣
                .map(future -> future.thenCompose(quote ->
                        CompletableFuture.supplyAsync(
                                () -> Discount.applyDiscount(quote), executor)
                ))
                .collect(toList());
        //等待流中的所有Future执行完毕,提取各自的返回值
        List<String> str = priceFutures.stream().map(CompletableFuture::join).collect(toList());
        System.out.print(str);

2126

使用的这三个map跟同步没有太大的区别,但是使用了CompletableFuture类提供的特性,在需要的地方把他们变成了异步操作。

thenApply方法:当第一个Future运行结束,返回CompletableFuture<String>对象转换为CompleTableFuture<Quote>对象。

thenCompose方法:将两个异步操作进行流水线,当第一个操作完成时,将其结果作为参数传递给第二个操作。换句话说,你可以创建两个CompletableFuture对象,对第一个对象调用thenCompose,并向其传递一个函数。

这个方法也有Async版本:thenComposeAsync,通常带后缀的版本是讲任务移交到一个新线程,不带后缀的在当前线程执行。对于这个例子我们没有加上后缀,因为对于最终结果,或者大致的时间而言都没有多少差别,少了很多线程切换的开销。

合并两个CompletableFuture,无论是否依赖

与上面不同,第二个CompletableFuture无需等待第一个CompletableFuture运行结束。而是,将两个完全不相干的CompletableFuture对象整合起来,不希望等到第一个任务完全结束才开始第二个任务。

这种情况应该使用thenCombine方法,它接受名为BiFunction的第二个参数,这个参数定义了当两个CompletableFuture对象完成计算后,结果如何合并。同thenCompose方法一样,thenCombine方法也提供了一个Async的版本。使用thenCombineAsync会导致BiFunction中定义的合并操作被提交到线程池中,由另一个任务以异步的方式执行。

回到这个例子,比如说我们现在需要第三个CompletableFuture来获取汇率,展示美元。当前两个CompletableFuture计算出结果,并由BiFunction方法完全合并后,由它来最终将诶书这一任务:

Future<Double> futurePriceUSD = CompletableFuture.supplyAsync(()->shops.get(0).getPrice("gg"))
                .thenCombine(
                        CompletableFuture.supplyAsync(
                                ()-> 0.66 //远程服务获取 汇率
                        ),(price,rate) -> price * rate
                );

这里 第一个参数price 是 getPrice的返回值 double , 第二个参数 rate 是第二个工厂方法返回的0.66 偷了个懒, 最后是他们的结果进行乘法操作 返回最终结果。

响应CompletableFuture的completion事件

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/e024cc39655ece152be623006fedb425.html