Ad

The Strange Behavior Of CompletableFuture

Why the below code does not print I just woke up

    import java.util.concurrent.CompletableFuture;
    public class CompletableFutureTest {
        public static void main(String[] args) {
            CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("I just woke up.");
            });
            System.out.println("I am main");
        }
    }

And the code given below prints I just woke up

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CompletableFutureTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("I just woke up.");
        }, executorService);
        executorService.shutdown();
        System.out.println("I am main");
    }
}

The possible noticeable difference between both the codes is that the second sample of code takes Single Thread pool into runAsync method, while the first one does not take any argument that is It uses ForkJoin pool. Please help me get the reason why is I just woke up not printed in first program

Ad

Answer

From ForkJoinPool

...All worker threads are initialized with Thread.isDaemon() set true.

From Executors.defaultThreadFactory

...Each new thread is created as a non-daemon thread.

From Thread.setDaemon

...The Java Virtual Machine exits when the only threads running are all daemon threads.

In the first case, the thread is coming from ForkJoinPool.commonPool and hence it is daemon.
And in the second case, the thread is created using Executors.defaultThreadFactory, so is non-daemon.

This explain the different behaviour.

Ad
source: stackoverflow.com
Ad