JEP 425: Virtual threads is targeted to JDK 19 as a preview API. Virtual threads are part of Project Loom, which has been in the making since 2017. The project is aimed at enhancing the concurrency performance in Java by letting the developer write and maintain concurrency applications with familiar APIs and use hardware resources more efficiently.
Virtual threads: overview
Concurrency in Java is handled by threads. Each thread executes its tasks independently of others and provides a stack trace, so it is easy to debug or profile them. There are two methods of working with threads. The first one is thread-per-request: a thread is dedicated to a request for its entire duration. Such a design is easy to write, handle, and debug, but we can’t have too many of them. Threads are implemented as wrappers around operating system threads, which are costly. So to scale an application efficiently, developers sometimes use a second method — asynchronous programming. In this case, threads don’t hold on to requests but rather return to a pool to handle other requests. Such request-handling style allows for a higher number of operations without increasing the number of threads, but makes it difficult to write code and understand the app’s behavior.
Virtual threads are the mechanism that enables the developers to preserve the clarity of thread-per-request programming and significantly increase a number of threads. Virtual threads are not tied to OS threads for the whole lifetime of the code. Instead, they capture an OS thread only while they perform their calculations, i.e. multiple virtual threads can share one OS thread.
Virtual threads are cheap and plentiful. In a situation when a program must perform 10,000 tasks concurrently, only 200 OS threads can be created, which means the throughput will be 200 tasks-per-second. But the code may easily create 10,000 virtual threads, so the throughput will be 10,000 tasks-per-second. The number of tasks can further be increased, for virtual threads, it doesn’t matter. Therefore, the application can be scaled efficiently with optimal hardware utilization.
At the same time, virtual threads are easy to debug, profile, and execute. JDK debuggers and profiles can step through virtual threads, analyze stack traces, and associate code events with the right threads. As virtual threads are part of the JDK, it uses its own scheduler, ForkJoinPool, to schedule the threads and run the code, which doesn’t need to be rewritten. Moreover, there is no need to pool virtual threads, because thread pools are used for expensive resources, and virtual threads are cheap and plentiful.
The following JDK components will be updated with this JEP:
Java Native Interface (JNI)
Debugging (JVM TI, JDWP, and JDI)
JDK Flight Recorder (JFR)
Java Management Extensions (JMX)
In addition, multiple tests will be conducted before JDK 19 release to ensure there are no unexpected regressions or effects on performance. Main risks associated with the proposal are related to compatibility due to changes introduced to the main APIs. The key risks and assumptions are listed on the JEP’s page.
Virtual thread will go well with structured concurrency, a new API for creating and managing threads with clear relationships between them.
Project Loom value for Java
JEP 425 is a major step towards integration of Project Loom into the JDK. The project will benefit all Java developers as it enables lightweight scalable concurrency as part of the JVM without the need for additional libraries or frameworks.
The significance of Loom for the Java language cannot be overestimated. In this article, we provided a short summary of virtual threads, but the project calls for a more detailed discussion in a separate article. Subscribe to our newsletter so as not to miss it!