You can read the motivation here.
I want something like fixed thread pool
(Executors.newFixedThreadPool()) but with threads dying off when they
are idle for too long, and re-created when they are needed again.
The most intuitive approach - set core size to 0, maximum pool size to
the bounding value, and the queue to [an unbounded queue]
- fails: no tasks get executed at all (consistently with Javadoc but - IMHO - a little bit counterintuitively).
executor.allowCoreThreadTimeOut(true);
can be used to get this behavior.
More details why no tasks get executed at all if corePoolSize = 0
is specified
From the Javadoc,
Using an unbounded queue (for example a LinkedBlockingQueue without a
predefined capacity) will cause new tasks to wait in the queue when
all corePoolSize threads are busy. Thus, no more than corePoolSize
threads will ever be created. (And the value of the maximumPoolSize
therefore doesn't have any effect.)
Hence, if you specify corePoolSize = 0
no threads will ever be created, and no tasks will be executed at all.
In practice, however, when the corePoolSize is zero, implementations does create one thread (tested with Sun JDK6 and OpenJDK11). So in practice, the tasks are executed, but no more than one thread is ever created, regardless of what maximumPoolSize
is specified. I'm not entirely sure why because according to the spec, it shouldn't create even one.
Below is my test code. This will only ever use one thread, but if you specify corePoolSize=10
, it will use 10. If you add allowCoreThreadTimeOut(true)
, then these threads can timeout.
LinkedBlockingQueue<Runnable> q = new LinkedBlockingQueue<Runnable>();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
0, // core threads
10, // max threads
2, TimeUnit.MILLISECONDS,
q
);
for (int i = 0; i < 10; i++) {
final int j = i;
executor.execute(() ->
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"TaskNo:" + j + ":" + Thread.currentThread().getName()
);
});
}
executor.shutdown();