What changed in Java 19
1 change across 1 question — each with the behaviour it replaced, because “and how did it work before?” is the follow-up.
Covered in depth
How do you size a thread pool, and what does an unbounded queue cost you?
Executors.newVirtualThreadPerTaskExecutor() — not a pool at all. It creates a virtual thread per task, so pool sizing stops being the question for blocking I/O.
Before: Every blocking call held a platform thread, so the pool size had to be tuned against how long tasks blocked rather than how much CPU they used.