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?

1 Answer 1

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();
5
  • Need call Future::get like futures.forEach(f -> f.get());. But it works iterate order. How can I solve this problem? Commented Jun 16, 2017 at 7:40
  • @KI-YOUNGBANG why do you need to call get() method? whenComplete gives you the result of execution.
    – ledniov
    Commented Jun 16, 2017 at 7: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. Commented Jun 16, 2017 at 8:00
  • 2
    @KI-YOUNGBANG you can do the following: CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); and wait until completion. Refer to this question.
    – ledniov
    Commented Jun 16, 2017 at 8:11
  • future.thenAccept(System.out::println) would be simpler than using whenComplete() if you don't care about the throwable
    – Didier L
    Commented Jun 16, 2017 at 22:01

Not the answer you're looking for? Browse other questions tagged or ask your own question.