Virtual threads (Java 21)
Run hundreds of thousands of blocking tasks on a few OS threads, using plain blocking code.
Open this lesson in the learning hubKey points
- A virtual thread is scheduled by the JVM, not the OS. Each starts tiny and grows on demand, so a million of them is realistic.
- When it blocks on I/O it unmounts from its carrier thread, freeing that OS thread to run something else immediately.
- Write ordinary blocking code. No callbacks and no reactive types, yet it scales. Stack traces and debuggers still make sense.
- Use
Executors.newVirtualThreadPerTaskExecutor(). Never pool virtual threads: one per task is the whole idea. - They only help I/O-bound work. CPU-bound work still wants roughly one thread per core.
- In Java 21, blocking inside
synchronizedpins the carrier thread, so preferReentrantLockthere. JDK 24 removed that limitation.
Example
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException {
AtomicInteger done = new AtomicInteger();
Instant start = Instant.now();
// 10,000 threads that mostly wait. With platform threads this would hurt.
try (ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000; i++) {
pool.submit(() -> { Thread.sleep(100); done.incrementAndGet(); return null; });
}
} // close() waits for every task to finish
System.out.println("tasks done : " + done.get());
System.out.println("elapsed : " + Duration.between(start, Instant.now()).toMillis() + " ms");
Thread v = Thread.ofVirtual().name("v-1").start(() -> System.out.println("hi from a virtual thread"));
v.join();
System.out.println("isVirtual : " + v.isVirtual());
}
}
Virtual threads make blocking code cheap again.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.