2

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

Yogesh Sharma
  • 280
  • 1
  • 13
  • 5
    From the documentation: "All worker threads are initialized Thread.isDaemon() set true." – Rob Spoor Feb 10 '22 at 13:54
  • 3
    To rephrase the comment from Rob: in the first case, as soon as `main()` exits all threads in the `ForkJoin` pool are immediately terminated (because all thread are daemon threads.) In the second case the created thread is not a daemon thread and therefore the ThreadPool only terminates after the currently running task has completed. – Thomas Kläger Feb 10 '22 at 14:28
  • Also, `shutdown()` waits afaik for all tasks to complete. – Johannes Kuhn Feb 10 '22 at 14:43

1 Answers1

4

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.

samabcde
  • 6,988
  • 2
  • 25
  • 41
  • 2
    Thanks, what i understood is that in ForkJoinPool the worker threads are Daemon and hence the jvm exits after printing `I am main` and does not care about what the daemon worker wants to output. am i correct? – Yogesh Sharma Feb 10 '22 at 16:31
  • Yes, you may also want to check the duplicate of this question. – samabcde Feb 11 '22 at 14:19