I was going through Java Concurrency In Practice and got stuck at the 8.3.1 Thread creation and teardown topic. The following footnote warns about keeping corePoolSize
to zero.
Developers are sometimes tempted to set the core size to zero so that the worker threads will eventually be torn down and therefore won’t prevent the JVM from exiting, but this can cause some strange-seeming behavior in thread pools that don’t use a SynchronousQueue for their work queue (as newCachedThreadPool does). If the pool is already at the core size, ThreadPoolExecutor creates a new thread only if the work queue is full. So tasks submitted to a thread pool with a work queue that has any capacity and a core size of zero will not execute until the queue fills up, which is usually not what is desired.
So to verify this I wrote this program which does not work as stated above.
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
Output: Hello
So, does the behavior of the program suggest that ThreadPoolExecutor
creates at least one thread if a task is submitted irrespective of corePoolSize=0
. If yes, then what is the warning about in the text book.
EDIT: Tested the code in jdk1.5.0_22 upon @S.K.'s suggestion with following change:
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(1));//Queue size is set to 1.
But with this change, the program terminates without printing any output.
So am I misinterpreting these statements from the book?
EDIT (@sjlee): It's hard to add code in the comment, so I'll add it as an edit here... Can you try out this modification and run it against both the latest JDK and JDK 1.5?
final int corePoolSize = 0;
ThreadPoolExecutor tp = new ThreadPoolExecutor(corePoolSize, 1, 5, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
// If the pool is already at the core size
if (tp.getPoolSize() == corePoolSize) {
ExecutorService ex = tp;
// So tasks submitted to a thread pool with a work queue that has any capacity
// and a core size of zero will not execute until the queue fills up.
// So, this should not execute until queue fills up.
ex.execute(() -> System.out.println("Hello"));
}
tp.shutdown();
if (tp.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("thread pool shut down. exiting.");
} else {
System.out.println("shutdown timed out. exiting.");
}
@sjlee Have posted the result in comments.
thread pool shut down. exiting.
and for jdk 1.8 isHello thread pool shut down. exiting.
– PermissivecorePoolSize
=0, the task does not execute. I am not able to understand that bit. – PermissiveLinkedBlockingQueue
does not allow to create a queue with size 0 and on the other handSynchronousQueue
indeed serves the purpose but I was trying to validate the text in the book. – PermissiveallowCoreThreadTimeOut allows you to request that all pool threads be able to time out; enable this feature with a core size of zero if you want a bounded thread pool with a bounded work queue but still have all the threads torn down when there is no work to do.
"enable this feature with a core size of zero" does not make sense. – Pulvinate