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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42504277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:41:39  来源:igfitidea点击:

Java 8 - Call methods async in parallel and combine their results

javaasynchronousjava-8

提问by saw303

I am new to the Java 8 concurrency features such as CompletableFutureand I hope you can help to get started with the following use case.

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

There is a service called TimeConsumingServicesthat provides time consuming operations which I'd like to run in parallel since all of them are independent.

有一个服务称为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();
  }
}

So far I implemented the following example and I have managed to call all three service methods in parallel.

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

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();
  }
}

Is there a way to collect the return values of each service call and invoke the method byte[]‘ convert(String, String, String)?

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

回答by Ash

To combine the result after you have returned them all you can do something like this

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

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

This will run all of your futures, wait for them all to complete, then as soon as they are all finished will call your convertmethod you mention.

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

回答by user2377971

After join you can simply get()values from future1like:

加入后,您可以简单地使用以下get()future1

String s1 = future1.get()

and so on

等等

回答by MBec

You can combine them using thenCombine()method if there is only 3 futures to complete:

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

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) {
}