I'm trying to understand some of the differences between ForkJoinPool and ThreadPoolExecutor, and the following caught my attention.
With ThreadPoolExecutor
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
es.execute(() -> System.out.println("Hello."));
es.shutdown();
}
This program will always print out "Hello." to the screen.
With ForkJoinPool
public static void main(String[] args) {
ForkJoinPool es = new ForkJoinPool(1);
es.execute(() -> System.out.println("Hello."));
es.shutdown();
}
This program will on occasion print out "Hello." to the screen.
What's going on here?
Note that if I take out the call to gracefully shutdown, the first program never terminates, but both otherwise behave the same.
I understand that the fork/join behavior is explainable by noting that the JVM simply doesn't wait for the executed thread to terminate, and sometimes the thread is lucky enough to run before main finishes. Why isn't this same behavior exhibited by the first solution?
I don't think the answer is that both actually behave the same and I'm just getting lucky when I run the first solution. Indeed, when I run the first solution 100 times, I get "Hello." all 100 times, but when I run the second 100 times, I get "Hello." roughly 10 times. Even if the word "always" is not precisely correct, it appears that there is a key difference between how the two work that is causing the apparently different behavior.
ForkJoinPool
is defined with daemon threads. That is, each Thread created by the FJP is setDaemon(true)
. Once there are only daemon threads running the JVM will terminate immediately.
You should probably shutdown
then awaitTermination
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With