Mastery
Mastery/Java/E. Concurrency
T1 · high-leverage

Virtual threads (Project Loom, Java 21) vs. platform threads

A platform Thread is a thin wrapper around one real OS thread -- expensive enough that thread pools exist specifically to avoid creating too many. A virtual thread is a JVM-managed lightweight thread; you can spin up hundreds of thousands of them, and a blocking call (like Thread.sleep) on a virtual thread doesn't block an OS thread underneath it -- the JVM parks it and reuses the carrier thread for other virtual threads.

java
Thread platformThread = Thread.ofPlatform().unstarted(() -> {});
Thread virtualThread = Thread.ofVirtual().unstarted(() -> {});
System.out.println("platform thread isVirtual(): " + platformThread.isVirtual());
System.out.println("virtual thread isVirtual(): " + virtualThread.isVirtual());

The practical payoff: 10,000 concurrent "blocking" sleeps finish together, not sequentially -- something that would exhaust a platform thread pool almost immediately:

java
import java.util.concurrent.*;

int numTasks = 10_000;
var latch = new CountDownLatch(numTasks);
long start = System.nanoTime();

try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < numTasks; i++) {
        executor.submit(() -> {
            try { Thread.sleep(20); } catch (InterruptedException ignored) {}
            latch.countDown();
        });
    }
    latch.await();
}

long elapsedMs = (System.nanoTime() - start) / 1_000_000;
System.out.println(numTasks + " virtual threads, each \"blocking\" for 20ms, all finished in ~" + elapsedMs
    + "ms -- not the ~200 seconds a small platform-thread pool running them sequentially would need");

Interview angle

A current-events question for any Java role in 2024+: "what problem do virtual threads actually solve?" The strong answer isn't "they're faster threads" — it's that they make blocking, synchronous-looking code cheap enough to use at massive concurrency, removing the historical pressure to rewrite everything in a reactive style just to handle high request volume.

In the industry

Virtual threads are rapidly becoming the default for high-throughput I/O-bound server code specifically because they let teams keep simple, blocking, easy-to-debug code (a normal try/catch, a normal stack trace) while getting the scalability that used to require reactive frameworks (Project Reactor, RxJava) with their notoriously harder debugging story. The main caveat production teams have hit early: code with synchronized blocks around blocking calls can "pin" a virtual thread to its carrier, which is an active area of guidance as adoption grows.