Java 8 CompletableFuture-扇出实现

Java 8 CompletableFuture-扇出实现,java,asynchronous,lambda,future,Java,Asynchronous,Lambda,Future,我想知道在Java8 Completable未来实现扇出型功能的最佳方式是什么。我最近重写了一个函数,该函数有一堆旧的Future实例,然后使用CompletableFuture在循环中调用get,对每一个实例进行阻塞,生成一个更干净的变量。然而,我看到性能下降了2倍,所以我假设我使用新API的方式不太正确。代码如下所示: if (!clinet.login()) { throw new LoginException("There was a login error");

我想知道在Java8 Completable未来实现扇出型功能的最佳方式是什么。我最近重写了一个函数,该函数有一堆旧的Future实例,然后使用CompletableFuture在循环中调用get,对每一个实例进行阻塞,生成一个更干净的变量。然而,我看到性能下降了2倍,所以我假设我使用新API的方式不太正确。代码如下所示:

if (!clinet.login()) {
        throw new LoginException("There was a login error");
    }
    CompletableFuture<List<String>> smths = CompletableFuture
            .supplyAsync(client::getSmth);

    CompletableFuture<List<Data>> smths2 = smths.thenApply(client::getInformation)
            .thenApplyAsync((list) -> list.stream().map(obj -> mapper.map(obj, Data.class)).collect(toList()));

    List<CompletableFuture<Map<String, AnotherData>>> waitGroup = new ArrayList<>();
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentileM12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentileM6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M24M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentileM6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentileM12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M24M));

    CompletableFuture
            .allOf(waitGroup.toArray(new CompletableFuture[waitGroup.size()]));

    List<Data> data = smths2.join();
    Map<String, Set<AnotherData>> volPercent = waitGroup.stream()
            .map(CompletableFuture::join)
            .flatMap((e) -> e.entrySet().stream())
            .collect(groupingBy(Map.Entry::getKey,
                    mapping(Map.Entry::getValue,
                            toSet())));

    data.forEach((d) -> {
        Set<AnotherData> asdasd = volPercent.get(d.getSymbol());
        if (asdasd != null) {
            d.add(asdasd);
        }
    });
    return stocks;
 List<String> symbols = client.block().get();
    Future<Map<String, Data>> smth = client.block2(symbols);
    Future<Map<String, Double>> ivM6MResultsFuture = clientB.getIvdataM6M(symbols);
    Future<Map<String, Double>> ivM12MResultsFuture = clientB.getIvdataM12M(symbols);
    Future<Map<String, Double>> iv2M6MResultsFuture = clientB.getIvdata2M6M(symbols);
    Future<Map<String, Double>> iv2M12MResultsFuture = clientB.getIvdata2M12M(symbols);
    Future<Map<String, Double>> iv2M24MResultsFuture = clientB.getIvdata2M24M(symbols);
    Future<Map<String, Double>> hvM6MResultsFuture = clientB.getHvdataM6M(symbols);
    Future<Map<String, Double>> hvM12MResultsFuture = clientB.getHvdataM12M(symbols);
    Future<Map<String, Double>> hv2M6MResultsFuture = clientB.getHvdata2M6M(symbols);
    Future<Map<String, Double>> hv2M12MResultsFuture = clientB.getHvdata2M12M(symbols);
    Future<Map<String, Double>> hv2M24MResultsFuture = clientB.getHvdata2M24M(symbols);
    Map<String, Data> doughResults = smth.get();
    Map<String, Double> ivM6MResults = ivM6MResultsFuture.get();
    Map<String, Double> ivM12MResults = ivM12MResultsFuture.get();
    Map<String, Double> iv2M6MResults = iv2M6MResultsFuture.get();
    Map<String, Double> iv2M12MResults = iv2M12MResultsFuture.get();
    Map<String, Double> iv2M24MResults = iv2M24MResultsFuture.get();
    Map<String, Double> hvM6MResults = hvM6MResultsFuture.get();
    Map<String, Double> hvM12MResults = hvM12MResultsFuture.get();
    Map<String, Double> hv2M6MResults = hv2M6MResultsFuture.get();
    Map<String, Double> hv2M12MResults = hv2M12MResultsFuture.get();
    Map<String, Double> hv2M24MResults = hv2M24MResultsFuture.get();
原始代码看起来是这样的:

if (!clinet.login()) {
        throw new LoginException("There was a login error");
    }
    CompletableFuture<List<String>> smths = CompletableFuture
            .supplyAsync(client::getSmth);

    CompletableFuture<List<Data>> smths2 = smths.thenApply(client::getInformation)
            .thenApplyAsync((list) -> list.stream().map(obj -> mapper.map(obj, Data.class)).collect(toList()));

    List<CompletableFuture<Map<String, AnotherData>>> waitGroup = new ArrayList<>();
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentileM12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentileM6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getIvPercentile2M24M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentileM6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M6M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentileM12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M12M));
    waitGroup.add(notablesFuture.thenComposeAsync(clientb::getHvPercentile2M24M));

    CompletableFuture
            .allOf(waitGroup.toArray(new CompletableFuture[waitGroup.size()]));

    List<Data> data = smths2.join();
    Map<String, Set<AnotherData>> volPercent = waitGroup.stream()
            .map(CompletableFuture::join)
            .flatMap((e) -> e.entrySet().stream())
            .collect(groupingBy(Map.Entry::getKey,
                    mapping(Map.Entry::getValue,
                            toSet())));

    data.forEach((d) -> {
        Set<AnotherData> asdasd = volPercent.get(d.getSymbol());
        if (asdasd != null) {
            d.add(asdasd);
        }
    });
    return stocks;
 List<String> symbols = client.block().get();
    Future<Map<String, Data>> smth = client.block2(symbols);
    Future<Map<String, Double>> ivM6MResultsFuture = clientB.getIvdataM6M(symbols);
    Future<Map<String, Double>> ivM12MResultsFuture = clientB.getIvdataM12M(symbols);
    Future<Map<String, Double>> iv2M6MResultsFuture = clientB.getIvdata2M6M(symbols);
    Future<Map<String, Double>> iv2M12MResultsFuture = clientB.getIvdata2M12M(symbols);
    Future<Map<String, Double>> iv2M24MResultsFuture = clientB.getIvdata2M24M(symbols);
    Future<Map<String, Double>> hvM6MResultsFuture = clientB.getHvdataM6M(symbols);
    Future<Map<String, Double>> hvM12MResultsFuture = clientB.getHvdataM12M(symbols);
    Future<Map<String, Double>> hv2M6MResultsFuture = clientB.getHvdata2M6M(symbols);
    Future<Map<String, Double>> hv2M12MResultsFuture = clientB.getHvdata2M12M(symbols);
    Future<Map<String, Double>> hv2M24MResultsFuture = clientB.getHvdata2M24M(symbols);
    Map<String, Data> doughResults = smth.get();
    Map<String, Double> ivM6MResults = ivM6MResultsFuture.get();
    Map<String, Double> ivM12MResults = ivM12MResultsFuture.get();
    Map<String, Double> iv2M6MResults = iv2M6MResultsFuture.get();
    Map<String, Double> iv2M12MResults = iv2M12MResultsFuture.get();
    Map<String, Double> iv2M24MResults = iv2M24MResultsFuture.get();
    Map<String, Double> hvM6MResults = hvM6MResultsFuture.get();
    Map<String, Double> hvM12MResults = hvM12MResultsFuture.get();
    Map<String, Double> hv2M6MResults = hv2M6MResultsFuture.get();
    Map<String, Double> hv2M12MResults = hv2M12MResultsFuture.get();
    Map<String, Double> hv2M24MResults = hv2M24MResultsFuture.get();
List symbols=client.block().get();
Future smth=客户端.block2(符号);
Future ivM6MResultsFuture=clientB.getIvdataM6M(符号);
Future ivM12MResultsFuture=clientB.getIvdataM12M(符号);
Future iv2M6MResultsFuture=clientB.getIvdata2M6M(符号);
Future iv2m12mresultsfourture=clientB.getIvdata2M12M(符号);
未来iv2M24MResultsFuture=clientB.getIvdata2M24M(符号);
Future hvM6MResultsFuture=clientB.getHvdataM6M(符号);
Future hvm1mresultsfuture=clientB.getHvdataM12M(符号);
Future hv2M6MResultsFuture=clientB.getHvdata2M6M(符号);
Future hv2m12mresultsfourture=clientB.getHvdata2M12M(符号);
未来hv2M24MResultsFuture=clientB.getHvdata2M24M(符号);
Map doughResults=smth.get();
映射ivM6MResults=ivM6MResultsFuture.get();
映射ivM12MResults=ivM12MResultsFuture.get();
Map iv2M6MResults=iv2M6MResultsFuture.get();
映射iv2M12MResults=iv2M12MResultsFuture.get();
映射iv2M24MResults=iv2M24MResultsFuture.get();
Map hvM6MResults=hvM6MResultsFuture.get();
映射hvM12MResults=hvM12MResultsFuture.get();
映射hv2M6MResults=hv2M6MResultsFuture.get();
映射HV2M12MSults=HV2M12MSultsFuture.get();
映射hv2M24MResults=hv2M24MResultsFuture.get();
使用一个大for循环将所有未来映射到一起并聚合结果。希望从代码中可以清楚地看出它在做什么,但本质上:

  • 我打了一个网络电话,得到一个列表
  • 根据这份清单,我 调用生成某些对象的内部服务
  • 基于第一个列表,我生成了一系列任务来获取各种数据
  • 我用3中的项目填充2中生成的对象- 实际上,2和3可以同时运行,因为它们不是 依赖的
  • 两个主要问题:

  • 您是否看到我的CompletableFuture使用中存在任何问题,以及根据概述的标准改进实现的空间,目前比常规blocking.get()old Futures慢约2倍,作为参考

  • 我对加入的方式有点恼火,不得不调用.allOf(),结果无效。在我缺少的API中,有没有更好的方法来实现这一点

  • 作为旁注,我意识到我在Java8变体中做了更多的工作,出现了大量的流和映射,但是时间差从旧版本的22秒到新版本的45秒,总项目大约是200个,所以大部分实际上是花在网络和等待上,而不是流操作上


    谢谢

    很难说,因为代码中有一些部分丢失了,但我会避免.join()的出现(因为它们会阻塞),而是通过waitGroup进行迭代,并使用combineAsync传递smths2。比如:

     return CompletableFuture.supplyAsync(() -> blockingNetworkCall(params, symbols)
                .entrySet().stream()
                .collect(Collectors.toMap(Map.Entry::getKey, value -> new Data(value.getValue(), TimePeriod.M1, TimePeriod.Y1))));
    
        Stream<CompletableFuture<AnotherData>> map = 
             waitGroup.stream().map(
                    cf -> cf.thenCombineAsync(
                           smths2, (m, l) -> {doWhatever(m, l)}
        ));
    
    流映射=
    waitGroup.stream().map(
    cf->cf.thenCombineAsync(
    smths2,(m,l)->{doWhatever(m,l)}
    ));
    
    只是一个想法