Reputation: 205
I'm kinda new to using CompletableFuture API and I have a question regarding usage of allOf
. From what I read, completable-future should be in complete state and allOf
logic should be executed when all associated futures complete, including completed-exceptionally
. But here's my smaple code for which allOf
block never gets executed -
public static void test() {
CompletableFuture<String> r1 = CompletableFuture.supplyAsync(() -> {
try{
Thread.sleep(1000);
throw new RuntimeException("blahh !!!");
}catch (Exception e) {
throw new RuntimeException(e);
}
});
CompletableFuture<String> r2 = CompletableFuture.supplyAsync(() -> "55");
CompletableFuture<String> r3 = CompletableFuture.supplyAsync(() -> "56");
CompletableFuture.allOf(r1, r2, r3).thenRun(() -> { System.out.println(Thread.currentThread()+" --- End."); });
Stream.of(r1, r2, r3).forEach(System.out::println);
try{
System.out.println(Thread.currentThread()+" --- SLEEPING !!!");
Thread.sleep(3000);
System.out.println(Thread.currentThread()+" --- DONE !!!");
} catch (Exception e) {
//e.printStackTrace();
}
Stream.of(r1, r2, r3).forEach(System.out::println);
}
Upvotes: 2
Views: 4128
Reputation: 45319
The problem is not that your allOf
CompletableFuture
never completes. It does.
What causes your code not to run is thenRun
's expectation:
Returns a new CompletionStage that, when this stage completes normally, executes the given action. See the CompletionStage documentation for rules covering exceptional completion.
You probably already know that when one of allOf
's futures completes exceptionally, the resulting future also completes exceptionally:
Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete. If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a CompletionException holding this exception as its cause.
In short, don't use thenRun
if you want to run an action on your allOf
future irrespective of how it comples. As an alternative, you can use whenComplete
:
CompletableFuture.allOf(r1, r2, r3)
.whenComplete((a, ex) -> System.out.println(Thread.currentThread() + " --- End."));
You can also use a combination of thenRun
+ exceptionally
, one of which will run:
CompletableFuture<Void> all = CompletableFuture.allOf(r1, r2, r3);
all.thenRun(() -> {
System.out.println(Thread.currentThread() + " --- End.");
});
all.exceptionally(ex -> {
System.out.println(ex);
return null;
});
Upvotes: 3