As we know, the java.util.concurrent.Executors
contains many methods such as
newCachedThreadPool
newFixedThreadPool
newScheduledThreadPool
newSingleThreadExecutor
newSingleThreadScheduledExecutor
They return ExecutorService
, which contains the execute(Runnable task)
method. However, when calling the execute(Runnable task)
of ExecutorService
returned from the aforementioned factory methods, it could only terminate by calling shutdown()
or shutdownNow()
For instance, if we add the following code to the main
method,
ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test"));
the calling the the main program will never terminate as the shutdown()
or shutdownNow()
is not called. So a program containing the following snippet in main will terminate
ExecutorService e = Executors.newSingleThreadExecutor();
e.execute(() -> system.out.println("test"));
e.shutdown();
However, some subclasses of ExecutorService
such as the one returned by calling Executors.newWorkStealingPool
or the ForkJoinPool
can terminate without calling shutdown()
or shutdownNow()
So my QUESTION is: why does the execute()
of the ExecutorService
returned from the aforementioned factory methods starting with "new" not terminate without calling shutdown()
or shutdownNow()
from the design point of view?
Briefly about java threads: there are two types of threads - daemon and non-daemon. The program terminates when all of its non-daemon threads have finished execution. Daemon threads can only run as long the program is running and do not block termination, e.g. garbage collector. When a java program starts all of its threads except the main thread are daemon.
newSingleThreadExecutor()
and its defaultThreadFactory()
create non-daemon threads. Which kinda makes sense - you're creating a pool of threads that wait for work, it should be your explicit intention to shut it down.
ForkJoinPool, on the other hand, abstracts you from the underlying thread pool. So it can use daemon threads, as it is generally your intention to wait for task execution anyways.