Java 8 - Call methods async in parallel and combin

2019-03-25 19:21发布

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

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

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)?

3条回答
爷的心禁止访问
2楼-- · 2019-03-25 20:01

After join you can simply get() values from future1 like:

String s1 = future1.get()

and so on

查看更多
smile是对你的礼貌
3楼-- · 2019-03-25 20:17

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 convert method you mention.

查看更多
姐就是有狂的资本
4楼-- · 2019-03-25 20:23

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

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) {
}
查看更多
登录 后发表回答