Java Virtual Threads
In this page:
What are Virtual Threads?
Virtual threads, finalized in Java 21 as part of Project Loom, are lightweight threads managed entirely by the JVM rather than mapped one-to-one to an operating system thread, allowing a program to run huge numbers of them cheaply.
Example: What are Virtual Threads?
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread vt = Thread.ofVirtual().start(() -> System.out.println("Running on a virtual thread")); // JVM-managed, lightweight
vt.join();
}
}
Login to try C/C++/Java/PHP code in the editor
Creating a Virtual Thread
Virtual threads are created using the new Thread.ofVirtual() builder or the shortcut Thread.startVirtualThread, both of which behave like a normal Thread from the calling code's perspective but carry far less overhead.
Example: Creating a Virtual Thread
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t1 = Thread.ofVirtual().start(() -> System.out.println("via ofVirtual()"));
Thread t2 = Thread.startVirtualThread(() -> System.out.println("via startVirtualThread")); // shortcut
t1.join(); t2.join();
}
}
Login to try C/C++/Java/PHP code in the editor
Virtual Threads vs Platform Threads
A platform thread, created with new Thread(), maps directly to a limited operating system thread, while a virtual thread is scheduled by the JVM onto a small pool of carrier threads, letting millions of virtual threads exist where only thousands of platform threads could.
Example: Virtual Threads vs Platform Threads
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread platform = new Thread(() -> System.out.println("Platform thread: " + Thread.currentThread()));
Thread virtual = Thread.ofVirtual().unstarted(() -> System.out.println("Virtual thread: " + Thread.currentThread()));
platform.start(); platform.join();
virtual.start(); virtual.join();
}
}
Login to try C/C++/Java/PHP code in the editor
Virtual Threads with ExecutorService
Executors.newVirtualThreadPerTaskExecutor() creates a new virtual thread for every task submitted to it, rather than reusing a fixed-size pool, which works well because virtual threads are cheap enough to create one per task.
Example: Virtual Threads with ExecutorService
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> System.out.println("New virtual thread per task"));
}
}
}
Login to try C/C++/Java/PHP code in the editor
When to Use Virtual Threads
Virtual threads are ideal for high-throughput, I/O-bound workloads like handling many concurrent network requests or database calls, since blocking a virtual thread is inexpensive, but they offer little benefit for CPU-bound computation, which is limited by processor cores instead of thread count.
Example: When to Use Virtual Threads
public class Main {
public static void main(String[] args) {
System.out.println("Good fit: many I/O-bound network/database calls");
System.out.println("Poor fit: CPU-bound computation, limited by processor cores");
}
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: