Java 8 - 并行调用方法异步并结合它们的结果

时间:2017-02-28 09:01:33

标签: java asynchronous java-8

我是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)

3 个答案:

答案 0 :(得分:10)

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

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

这将运行你所有的未来,等待它们全部完成,然后一旦完成它们就会调用你提到的convert方法。

答案 1 :(得分:4)

加入后,您只需get() future1的{​​{1}}值即可:

String s1 = future1.get()

等等

答案 2 :(得分:1)

如果只有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) {
}