Yesterday's event loop bought its efficiency by forbidding blocking code. Everything became callbacks and chains: fast, and genuinely harder to read, debug and reason about. Java went at the other side of the problem and attacked the cost of a thread.
A platform thread is an operating system thread — megabytes of stack, scheduled by the kernel. A virtual thread is a Java object. When it blocks on I/O the runtime lifts it off its carrier thread and parks it on the heap, and the OS thread goes and serves someone else.
The straightforward, sequential style works again: familiar libraries, real stack traces, ordinary profilers, and millions of threads where there used to be thousands.
It adds no CPU cores. CPU-bound work gains nothing, and a virtual thread parked on a lock you hold still blocks everything queued behind it. The win belongs to work that spends its life waiting.
Sometimes the right move isn't accepting a hard trade-off. It's making the expensive thing cheap enough that the trade disappears.
