Why architecture matters here
Java servers historically capped concurrency at a few thousand due to OS thread costs (memory, context switch). Reactive frameworks and async callbacks worked around this by never blocking, at the cost of complex code. Virtual threads let you write straightforward blocking code and still handle a million connections.
The architecture matters because the abstraction is not free everywhere. Pinning cases (synchronized on a resource that yields, JNI calls) hold a carrier thread and limit concurrency. Structured concurrency changes how you compose tasks. Diagnostics require understanding of the mount/unmount model.
Get it right and you retire your thread pool tuning; get it wrong and you have a subtle scalability wall.
The architecture: every piece explained
The top strip is the runtime. A Virtual thread is a Java Thread object that is not backed by an OS thread. Its state is a Continuation — a captured call stack that can be paused and resumed. A Carrier thread is an ordinary platform thread from a ForkJoinPool that runs virtual threads. The Scheduler is work-stealing across carriers.
The middle row is the mechanics. Park / unpark is what happens at a blocking operation — the virtual thread's continuation is saved, and the carrier is released to run another virtual thread. Pinning is when a virtual thread cannot unmount — inside a synchronized block, or during a JNI call — and holds its carrier. Structured concurrency introduces StructuredTaskScope for composing parallel work with join and cancellation semantics. Scoped values propagate immutable context down virtual thread hierarchies.
The lower rows are practice. Interop means most existing Java code (NIO, JDBC drivers with virtual-thread-friendly locks) works. Diagnostics — thread dumps and JFR — expose virtual thread state. Ops means removing thread-pool sizing as a knob and instead monitoring pinning rates and carrier saturation.
End-to-end flow
End-to-end: a Java 21 web server accepts 100,000 concurrent HTTP connections. Each connection is a virtual thread that does a JDBC query, waits for a downstream API, and returns a response. When the JDBC call blocks, the continuation is saved; the carrier picks another virtual thread. When the downstream API responds, unpark schedules the virtual thread to resume on any available carrier. Under load, JFR reports 42 carrier threads running 82,000 concurrent virtual threads with no pinning. Latency is stable; throughput scales linearly with cores. Compare to an old thread pool of 200 platform threads that would have queued the excess and inflated tail latency.