All topics
library
advanced

Virtual Threads (Java 21)

Use lightweight virtual threads for high-concurrency I/O workloads without the overhead of platform threads.

Virtual threads (Project Loom, preview in Java 19, stable in Java 21) are lightweight threads managed by the JVM, not the OS. You can create millions of them without exhausting system resources.

Platform threads = taxis (expensive, limited supply). Virtual threads = rideshare (millions of passengers, shared small car fleet that picks up whoever is ready to move).

Key Concepts

1
Platform threads (traditional) map 1:1 to OS threads. They're expensive (~1MB stack each, OS scheduling overhead). Creating thousands is impractical.
2
Virtual threads are scheduled by the JVM on a small pool of carrier (platform) threads. When a virtual thread blocks on I/O, the JVM unmounts it from the carrier and mounts another virtual thread — no OS thread is wasted waiting.
3
Creation: Thread.ofVirtual().start(runnable) or Executors.newVirtualThreadPerTaskExecutor(). Virtual threads are daemon threads and have no thread pool size limit.
4
Key benefit: write synchronous, blocking code that scales like async code. No need for reactive frameworks (WebFlux, CompletableFuture chains) for I/O-bound workloads.
5
Limitations: - CPU-bound work doesn't benefit (only one carrier thread runs at a time per core) - synchronized blocks pin the virtual thread to its carrier (use ReentrantLock instead) - ThreadLocal works but can be memory-heavy with millions of threads (use ScopedValues instead)
6
This is the biggest concurrency change since Java 5's java.util.concurrent.