Unlock Massive Throughput with Java’s New Virtual Threads (JEP 425)
This article explains Java's preview virtual threads (JEP 425), how they differ from traditional platform threads, demonstrates their superior scalability with code examples, and provides step‑by‑step instructions to enable them in the JDK.
OpenJDK JEP 425 introduces virtual threads (a preview coroutine feature) that provide lightweight threads, dramatically reducing the effort required to write, maintain, and observe high‑throughput concurrent applications.
Traditionally Java relies on platform threads, which are wrappers around operating‑system (OS) threads. Each platform thread maps one‑to‑one with an OS thread, incurring high cost and limiting the number of concurrent threads to the OS limit, thus throttling application throughput.
About virtual threads
A java.lang.Thread created as a virtual thread runs Java code on an underlying OS thread but does not bind its lifetime to a specific OS thread instance, allowing many virtual threads to share the same OS thread.
Virtual threads are a lightweight implementation supplied by the JDK, a form of user‑mode threads. Early Java versions called similar constructs “green threads” (M:1 scheduling). Modern platform threads use 1:1 scheduling, while virtual threads adopt M:N scheduling, mapping many virtual threads onto fewer OS threads.
Higher throughput
Developers can choose virtual or platform threads, but virtual threads deliver far better throughput in server applications. The following example creates 10 000 virtual threads that each sleep for one second:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
IntStream.range(0, 10_000).forEach(i -> {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return i;
});
});
} // executor.close() is called implicitly, and waitsModern hardware can easily run 10 000 virtual threads concurrently. Using a platform‑thread executor such as Executors.newCachedThreadPool() would attempt to create 10 000 OS threads and typically crash the program. A fixed‑size pool (e.g., 200 threads) would serialize the tasks, yielding only about 200 tasks per second.
With 200 platform threads the throughput is roughly 200 tasks/second, whereas virtual threads can achieve about 10 000 tasks/second after warm‑up. Scaling the example to 1 000 000 tasks shows virtual threads can approach one million tasks per second, a throughput impossible with platform threads.
In summary, virtual threads are not faster per se; they do not reduce the execution speed of individual code paths. Their advantage lies in providing massive scalability (higher throughput) rather than lower latency.
How to enable virtual threads?
Virtual threads are currently a preview feature in Java and are disabled by default. To try them on a JDK version, enable the preview API during compilation and execution:
Compile with javac --release XX --enable-preview Main.java and run with java --enable-preview Main.
When using the source‑code launcher, run with java --release XX --enable-preview Main.java.
Start jshell with jshell --enable-preview.
More information is available in OpenJDK’s JDK Issue‑8277131. The proposal was created on 2021‑11‑15 and is still in the early stage of the JEP process.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
