37. Virtual Threads (Project Loom)
Virtual threads (Java 21, Project Loom) are lightweight JVM-managed threads that dramatically reduce the cost of blocking I/O โ you can create millions of them without the memory and scheduling overhead of OS threads.
Java 21+ (standard)Explanation
Platform (OS) threads are expensive: each requires ~1 MB of stack space and an OS context switch. Virtual threads are cheap JVM-level coroutines โ they park on a carrier OS thread when blocked (I/O, sleep, lock) and resume on any available carrier thread when ready. You can create millions of virtual threads without exhausting resources.
Virtual threads are Thread instances โ they use the same Thread API, so existing libraries work transparently. Create them with Thread.ofVirtual().start(...) or Executors.newVirtualThreadPerTaskExecutor().
Key limitation: pinning. A virtual thread is pinned to its carrier OS thread when it blocks inside a synchronized block/method, preventing the carrier from running other virtual threads. Avoid synchronized in virtual-thread-heavy code โ use java.util.concurrent.locks.ReentrantLock instead. Pinning is detectable via JFR event jdk.VirtualThreadPinned.
Example
import java.util.concurrent.Executors;
public class VirtualThreadsDemo {
static void blockingTask(int id) throws InterruptedException {
System.out.printf("Task %d starting on %s%n", id, Thread.currentThread());
Thread.sleep(100); // parks virtual thread, frees carrier
System.out.printf("Task %d finished%n", id);
}
public static void main(String[] args) throws InterruptedException {
// Old way: 1000 platform threads would be very expensive
// New way: 1000 virtual threads โ cheap!
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10; i++) {
final int id = i;
executor.submit(() -> {
try { blockingTask(id); }
catch (InterruptedException e) { Thread.currentThread().interrupt(); }
});
}
} // executor.close() waits for all tasks
// Single virtual thread
Thread vThread = Thread.ofVirtual()
.name("my-virtual-thread")
.start(() -> System.out.println("Running in: " + Thread.currentThread()));
vThread.join();
System.out.println("Is virtual: " + vThread.isVirtual()); // true
// Virtual thread per task โ great for high-concurrency servers
System.out.println("Main thread is virtual: " + Thread.currentThread().isVirtual());
}
}Sources
- https://openjdk.org/jeps/444 โ JEP 444: Virtual Threads (standard, Java 21)
- https://dev.java/learn/new-features/virtual-threads/ โ Virtual threads guide