Under The Hood
backend java Java 21 (JEP 444, virtual threads stable)

Java Virtual Threads (Project Loom)

Last updated
Prerequisites:
Java threading basics
Understanding of blocking I/O and thread-per-request servers
  • java
  • virtual-threads
  • loom
  • concurrency
  • threading
  • jvm

Read at your depth

The practical view

Virtual threads let you write blocking-style code that scales like async code: Thread.ofVirtual().start(() -> { var r = client.get(url); process(r); }); or Executors.newVirtualThreadPerTaskExecutor(). Each virtual thread is a Java Thread instance, but it is scheduled onto a small pool of platform (carrier) threads by the JVM. When a virtual thread blocks on I/O, the JVM unmounts it from the carrier, runs other virtual threads on that carrier, and remounts it when the I/O completes. You keep normal try-with-resources, blocking calls, and stack traces — no CompletableFuture or reactive chains needed.

Legacy vs modern

Platform thread-per-request vs virtual thread-per-request

A platform thread per request is capped by OS resources; virtual threads make the thread count a heap concern, keeping blocking code readable.

before → after
Fixed platform thread pool
ExecutorService pool = Executors.newFixedThreadPool(200);
pool.submit(() -> handle(request));
Virtual thread per task
try (var pool = Executors.newVirtualThreadPerTaskExecutor()) {
  pool.submit(() -> handle(request));
}

Interview gotchas

Under The Hood — a multi-depth technical interview hub.

Press ⌘ K to search.