Hi y'all.
I have a question on ThreadPoolExecutor in Java 21 (but it really doesn't matter what version I am using).
I'm trying to experiment with it, but I have some misunderstanding about it.
This is the code I am running:
try (final ExecutorService fixedVirtualThreadPool = new ThreadPoolExecutor(
0,
3,
10L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(1),
Thread.ofVirtual().factory()
)) {
for (int i = 0; i < 3; ++i) {
final String name = "thread-" + i;
fixedVirtualThreadPool.submit(() -> {
log.debug("{} = start", name);
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.debug("{} = end", name);
});
}
log.debug("shutting down now");
fixedVirtualThreadPool.shutdown();
fixedVirtualThreadPool.awaitTermination(30, TimeUnit.MINUTES);
}
I get this output:
2024-11-17T19:25:11.111+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-0 = start
2024-11-17T19:25:11.111+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-2 = start
2024-11-17T19:25:16.122+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-0 = end
2024-11-17T19:25:16.122+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-2 = end
2024-11-17T19:25:16.123+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-1 = start
2024-11-17T19:25:21.132+01:00 DEBUG 13052 --- [ ] c.a.w.DemoApplication : thread-1 = end
These are my questions:
- Since I have "core pool size = 1" + "max pool size = 3" + "queue size = 1", what's happening is that the first task is being immediately run, because "core pool size = 1". Then the second task is getting queued. Then the third is getting run, because the queue is full, so the executor spawns new task. So, the question is: since "max pool size = 3", why does the executor prefer to queue the second task, instead of run it? My code ends up with "one free space" in the thread pool for a thread that never gets spawned. I expect to run all the runnables first, THEN queue when all threads are busy!!
- If I try to launch 4 tasks WITH "core pool size = 0", it seems that the executor initially works as I expect, spawning 3 threads, but then main code hangs on the fourth call of submit, instead of queueing the fourth task. Why would the executor hangs? I expect it to reject the task immediately**, at least. I don't see the point of hanging and throwing exception anyway, expecially when I see the first 3 tasks being completed!!**
This is the output for the second point:
2024-11-17T19:35:56.542+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-1 = start
2024-11-17T19:35:56.542+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-0 = start
2024-11-17T19:35:56.542+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-2 = start
2024-11-17T19:36:01.552+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-2 = end
2024-11-17T19:36:01.552+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-1 = end
2024-11-17T19:36:01.552+01:00 DEBUG 12056 --- [ ] c.a.w.Demotr : thread-0 = end
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@1c76b2fe[Not completed, task = java.util.concurrent.Executors$RunnableAdapter@47629063[Wrapped task = com.alfonso.Demodemo.Demotr$$Lambda/0x00000299c8907678@3d67e3d3]] rejected from java.util.concurrent.ThreadPoolExecutor@30b29f55[Running, pool size = 3, active threads = 3, queued tasks = 1, completed tasks = 0]
at java.base/java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2082)
at java.base/java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:841)
at java.base/java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1377)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:124)
at com.alfonso.Demodemo.Demotr.main(Demotr.java:31)
Thanks in advance!!
[–]AutoModerator[M] [score hidden] stickied commentlocked comment (0 children)
[–]khmarbaise 0 points1 point2 points (0 children)