Java Virtual Threads: What They Change
Virtual threads in Java 21 make high-throughput concurrent applications simpler without reactive frameworks.
Key Insights
- Virtual threads are lightweight and managed by the JVM, not the OS
- They eliminate the need for reactive frameworks in most I/O-bound applications
- Existing synchronized code may need refactoring to avoid pinning virtual threads
The Problem They Solve
Traditional Java threads map 1:1 to OS threads. This limits concurrency to thousands of threads at most. Virtual threads remove that constraint:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 100_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
}
When to Use Them
Virtual threads excel at I/O-bound workloads: HTTP servers, database queries, file operations. They don’t help CPU-bound tasks since those still need real CPU cores.
Migration Considerations
Replace thread pools with virtual thread executors. Watch for synchronized blocks that perform I/O — these pin the carrier thread. Use ReentrantLock instead.