【问题标题】:Java 8 - Call methods async in parallel and combine their resultsJava 8 - 并行调用异步方法并组合它们的结果
【发布时间】:2017-02-28 09:01:33
【问题描述】:

我是 Java 8 并发功能(例如 CompletableFuture)的新手,希望您能帮助开始使用以下用例。

有一个名为 TimeConsumingServices 的服务提供耗时的操作,我希望这些操作可以并行运行,因为它们都是独立的。

interface TimeConsumingService {

  default String hello(String name) {
    System.out.println(System.currentTimeMillis() + " > hello " + name);
    return "Hello " + name;
  }
  default String planet(String name) {
    System.out.println(System.currentTimeMillis() + " > planet " + name);
    return "Planet: " + name;
  }
  default String echo(String name) {
    System.out.println(System.currentTimeMillis() + " > echo " + name);
    return name;
  }

  default byte[] convert(String hello, String planet, String echo) {
    StringBuilder sb = new StringBuilder();
    sb.append(hello);
    sb.append(planet);
    sb.append(echo);
    return sb.toString().getBytes();
  }
}

到目前为止,我实现了以下示例,并且成功地并行调用了所有三个服务方法。

public class Runner implements TimeConsumingService {

  public static void main(String[] args) {
    new Runner().doStuffAsync();
  }

  public void doStuffAsync() {
    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> this.hello("Friend"));
    CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> this.planet("Earth"));
    CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> this.echo("Where is my echo?"));

    CompletableFuture.allOf(future1, future2, future3).join();
  }
}

有没有办法收集每个服务调用的返回值并调用方法byte[]‘ convert(String, String, String)

【问题讨论】:

    标签: java asynchronous java-8


    【解决方案1】:

    要在您返回所有结果后合并结果,您可以执行以下操作

    CompletableFuture<byte[]> byteFuture = CompletableFuture.allOf(cf1, cf2, cf3)
                         .thenApplyAsync(aVoid -> convert(cf1.join(), cf2.join(), cf3.join()));
    byte[] bytes = byteFuture.join();
    

    这将运行您所有的期货,等待它们全部完成,然后在它们全部完成后立即调用您提到的 convert 方法。

    【讨论】:

      【解决方案2】:

      加入后,您可以简单地从future1 中获取get() 值,例如:

      String s1 = future1.get()
      

      等等

      【讨论】:

      • 但是如果我调用 future1.get(); future2.get(); future3.get(); 他们不会被并行调用,不是吗?
      • 当您调用 future1.get() 时,您只会得到已经计算好的结果。
      • 是的,获取结果不是并行调用的,但所有方法都将异步计算。您可以通过添加TimeUnit.seconds(2).sleep() 进行检查;加入方法后。您会看到在睡眠之前调用了 System.out.println
      • @saw303 考虑将您的Futures 存储在列表中,而不是作为单个变量。然后你可以循环它们来使用结果。
      • 您可以查看我关于CompletableFuture 的旧问题并使用流stackoverflow.com/questions/41392286/… 处理它
      【解决方案3】:

      如果只需要完成 3 个期货,您可以使用thenCombine() 方法将它们组合起来:

      final CompletableFuture<byte[]> byteFuture = future1.thenCombine(future2, (t, u) -> {
          StringBuilder sb = new StringBuilder();
          sb.append(t);
          sb.append(u);
          return sb.toString();
      }).thenCombine(future3, (t, u) -> {
          StringBuilder sb = new StringBuilder();
          sb.append(t);
          sb.append(u);
          return sb.toString();
      }).thenApply(s -> s.getBytes());
      
      try {
          final byte[] get = byteFuture.get();
      } catch (InterruptedException | ExecutionException ex) {
      }
      

      【讨论】:

        猜你喜欢
        • 2021-07-15
        • 2016-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-26
        • 1970-01-01
        相关资源
        最近更新 更多