1

I have some service return CompletableFutures like this

Set<CompletableFuture<String>> futures = service.getSomething();

for (CompletableFuture<String> future : futures) {
    System.out.println(future.get());
}

This code prints value iterate order. But I want fast result print first like using CompletionService.

Set<CompletableFuture<String>> futures = service.getSomething();
Set<CompletableFuture<String>> donefutures = new HashSet<>();

while (true) {
    if (futures.equals(donefutures)) {
        break;
    }

    futures
            .stream()
            .filter(f -> !donefutures.contains(f))
            .filter(CompletableFuture::isDone)
            .peek(donefutures::add)
            .map(f -> {
                try {
                    return f.get();
                } catch (InterruptedException | ExecutionException e) {
                    return null;
                }
            })
            .forEach(System.out::println);

    Thread.sleep(100);
}

I tried this way. It's working. But I think really ugly. Is there better way?

KI-YOUNG BANG
  • 199
  • 1
  • 10

1 Answers1

1

You are working with CompletableFuture like with Future in a blocking way running an infinite loop. You have to specify callback function which will be invoked when your future completes.

So you can do something like this:

Set<CompletableFuture<String>> futures = service.getSomething();
futures.forEach(future -> future.whenComplete(
        (result, throwable) -> System.out.println(result)
));

CompletableFuture
    .allOf(futures.toArray(new CompletableFuture[0]))
    .join();
ledniov
  • 2,302
  • 3
  • 21
  • 27
  • Need call Future::get like `futures.forEach(f -> f.get());`. But it works iterate order. How can I solve this problem? – KI-YOUNG BANG Jun 16 '17 at 07:40
  • @KI-YOUNGBANG why do you need to call `get()` method? `whenComplete` gives you the result of execution. – ledniov Jun 16 '17 at 07:51
  • I want wait until all of futures done. I just tested `futures.forEach(f -> f.get());` worked. Because latest future.get() blocked and others whenComplete invoked. But I don't know this way is correct. – KI-YOUNG BANG Jun 16 '17 at 08:00
  • 2
    @KI-YOUNGBANG you can do the following: `CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();` and wait until completion. Refer to [this](https://stackoverflow.com/q/30705981/1126831) question. – ledniov Jun 16 '17 at 08:11
  • `future.thenAccept(System.out::println)` would be simpler than using `whenComplete()` if you don't care about the `throwable` – Didier L Jun 16 '17 at 22:01