My problem is related to the executor returned by Executors.newFixedThreadPool(1)
which is explained after the following program:
public static void main(String[] args) throws InterruptedException {
AtomicInteger atomicInteger = new AtomicInteger(0);
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
List<Runnable> runnableList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
runnableList.add(task(atomicInteger.incrementAndGet(), threadPoolExecutor));
}
System.out.println("Starting Stage-1.");
threadPoolExecutor.setCorePoolSize(4);
runnableList.forEach(threadPoolExecutor::execute);
waitForCompletion(threadPoolExecutor);
System.out.println("Stage-1 complete.");
threadPoolExecutor.setCorePoolSize(0);
TimeUnit.SECONDS.sleep(10);
System.out.println("Starting Stage-2.");
threadPoolExecutor.setCorePoolSize(6);
runnableList.forEach(threadPoolExecutor::execute);
waitForCompletion(threadPoolExecutor);
System.out.println("Stage-2 complete.");
threadPoolExecutor.shutdown();
}
static Runnable task(int count, ThreadPoolExecutor threadPoolExecutor) {
return () -> {
LocalTime start;
LocalTime end;
try {
start = LocalTime.now();
TimeUnit.SECONDS.sleep(5);
end = LocalTime.now();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
String log = "Thread: " + count +
", Start: " + start +
", Stop: " + end +
", ActiveCount: " + threadPoolExecutor.getActiveCount() +
", CorePoolSize: " + threadPoolExecutor.getCorePoolSize();
System.out.println(log);
};
}
static void waitForCompletion(ThreadPoolExecutor threadPoolExecutor) throws InterruptedException {
while (threadPoolExecutor.getActiveCount() != 0) {
TimeUnit.SECONDS.sleep(5);
}
}
Output:
Starting Stage-1.
Thread: 2, Start: 18:27:07.482, Stop: 18:27:12.487, ActiveCount: 4, CorePoolSize: 4
Thread: 3, Start: 18:27:07.482, Stop: 18:27:12.487, ActiveCount: 4, CorePoolSize: 4
Thread: 1, Start: 18:27:07.482, Stop: 18:27:12.487, ActiveCount: 4, CorePoolSize: 4
Thread: 4, Start: 18:27:07.482, Stop: 18:27:12.487, ActiveCount: 4, CorePoolSize: 4
Thread: 5, Start: 18:27:12.488, Stop: 18:27:17.491, ActiveCount: 1, CorePoolSize: 4
Thread: 6, Start: 18:27:17.492, Stop: 18:27:22.497, ActiveCount: 1, CorePoolSize: 4
Thread: 7, Start: 18:27:22.497, Stop: 18:27:27.502, ActiveCount: 1, CorePoolSize: 4
Thread: 8, Start: 18:27:27.502, Stop: 18:27:32.506, ActiveCount: 1, CorePoolSize: 4
Thread: 9, Start: 18:27:32.506, Stop: 18:27:37.512, ActiveCount: 1, CorePoolSize: 4
Thread: 10, Start: 18:27:37.512, Stop: 18:27:42.515, ActiveCount: 1, CorePoolSize: 4
Stage-1 complete.
Starting Stage-2.
Thread: 3, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 6, CorePoolSize: 6
Thread: 5, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 6, CorePoolSize: 6
Thread: 6, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 5, CorePoolSize: 6
Thread: 4, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 3, CorePoolSize: 6
Thread: 2, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 3, CorePoolSize: 6
Thread: 1, Start: 18:27:57.504, Stop: 18:28:02.506, ActiveCount: 1, CorePoolSize: 6
Thread: 7, Start: 18:28:02.507, Stop: 18:28:07.512, ActiveCount: 1, CorePoolSize: 6
Thread: 8, Start: 18:28:07.512, Stop: 18:28:12.517, ActiveCount: 1, CorePoolSize: 6
Thread: 9, Start: 18:28:12.517, Stop: 18:28:17.522, ActiveCount: 1, CorePoolSize: 6
Thread: 10, Start: 18:28:17.522, Stop: 18:28:22.524, ActiveCount: 1, CorePoolSize: 6
Stage-2 complete.
In the above program, you will see the 10 Threads being executed, first with a corePoolSize of 4. After the execution of the first four threads, the execution continues executing sequentially even though the corePoolSize is set higher than 1. I have demonstrated the above findings twice with 2 stages with corePoolSize of 4 and 6, confirming the uniformity of the behaviour.
My expectation is when there is empty slot in the executor, it should utilise that.
I am answering my question. Thanks to @tgdavies for providing the exception thrown in JDK 20. The solution is to increase the maxPoolSize.
After setting the maxPoolSize to something like
threadPoolExecutor.setMaximumPoolSize(Runtime.getRuntime().availableProcessors());
Things are executing parallely.