By default CompletableFuture
uses own ForkJoinPool.commonPool() (see CompletableFuture
implementation). And this default pool creates only daemon threads, e.g. they won’t block the main application from terminating if they still alive.
You have the following choices:
-
Collect all
CompletionStage
to some array and then makejava.util.concurrent.CompletableFuture#allOf()
.toCompletableFuture().join()
– this will guarantee all the stages are completed before going after join() -
Use *Async operations with your own thread pool which contains only non-daemon threads, like in the following example:
public static void main(String[] args) throws InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(10, r -> { Thread t = new Thread(r); t.setDaemon(false); // must be not daemon return t; }); for (int i = 0; i < 100; i++) { final int a = i; // the operation must be Async with our thread pool CompletableFuture<Boolean> cf = CompletableFuture.supplyAsync(() -> doPost(a), pool); cf.thenRun(() -> System.out.printf("%s: Run_%s%n", Thread.currentThread().getName(), a)); } pool.shutdown(); // without this the main application will be blocked forever } private static boolean doPost(int t) { System.out.printf("%s: Post_%s%n", Thread.currentThread().getName(), t); return true; }