Writing simpler reactive REST services with Quarkus Virtual Thread support

This means that existing Java code that processes requests will easily run in a virtual thread. Many server frameworks will choose to do this automatically, starting a new virtual thread for every incoming request and running the application’s business logic in it. Virtual threads, available as a preview release in JDK 19 and 20, are lightweight, inexpensive, and easy to create. They are tied to a platform thread that is connected to the operating system thread. Consequently, we no longer tie up platform threads in our applications and can handle more concurrent requests.

java virtual threads

I think that programmers won’t use Loom directly on a daily basis. It is more about when the vast number of libraries and frameworks will implement support for Loom. At this point, the application should be up and connected to a dockerized Postgresql database. Virtual threads solve high throughput demands that can’t be solved by standard threads due to the limit of CPU cores.

What is the performance impact of virtual threads?

Since then Java threading, with its Future, ExecutorService, ForkJoinPool, Concurrent_ maps, and many more, has matured. Starting thousends of threads may cause a system crash, and that’s why we use thread pools, to limit the amount of threads and reuse them. Virtual threads, also known as fibers or green threads, are a new feature introduced in JDK 21 that allows developers to create lightweight threads that are managed by the JVM rather than the operating system.

It is Kubernetes-friendly and allows applications to be run on OpenJDK HotSpot and GraalVM. Quarkus supports both imperative and reactive programming, whereas the former is implemented natively using Netty and Mutiny. Throughout the years, they were evolving and adapting to new hardware possibilities. Starting with Green Threads they quickly became platform threads by default, only to expand to the Concurrency API introduced in Java 1.5.

Get support

They are not designed to speed up computation and gain low latency. The standard way of handling parallel and concurrency computations in Java is to use threads. I’m a Husband, Father, Spring Developer Advocate and maker of things from Cleveland Ohio. I created this website as a place to document my journey as I learn new things and share them with you.

java virtual threads

It usually requires little awareness of concurrency because most requests are independent of each other. Unfortunately, as programs scale, this approach is on a collision course with the memory characteristics of platform threads. The vast majority of blocking operations in the JDK will unmount the virtual thread, freeing its carrier and the underlying OS thread to take on new work. However, some blocking operations in the JDK do not unmount the virtual thread, and thus block both its carrier and the underlying OS thread.

2. Scalability Issues with Platform Threads

The default pool size equals the number of CPU cores, and the maximum pool size is at most 256. The minimum number of core threads not blocked allowed is half the pool size. In such an approach, every thread can use its own local variable to store information. The need to share mutable states among threads, the well-known “hard part” of concurrent programming, drastically decreases.

When using virtual threads in quarkus, the number of virtual threads simultaneously living in the service is directly related to the incoming traffic. It is possible to get hundreds of thousands, if not millions, of them. When using Mutiny, alternative “xAndAwait” methods are provided to be used with virtual threads.

1. DO NOT Pool the Virtual Threads

The main problem is that Thread.currentThread() is used, directly or indirectly, pervasively in existing code (e.g., in determining lock ownership, or for thread-local variables). This method must return an object that represents the current thread of execution. If we introduced a new class to represent user-mode threads then currentThread() would have to return some sort of wrapper object that looks like a Thread but delegates to the user-mode thread object.

  • Parking virtual thread results in yielding its continuation, and unparking it result in the continuation being resubmitted to the scheduler.
  • New functions support the bulk suspension and resumption of virtual threads; these require the can_support_virtual_threads capability.
  • A new method in com.sun.jdi.ThreadReference tests if a thread is a virtual thread.
  • Another important note is that virtual threads are always daemon threads, meaning they’ll keep the containing JVM process alive until they complete.

However, once news spreads about your exceptional new application, you may start experiencing a high volume of traffic that could cause it to crash. If you notice in line #1, we are creating a ‘BACKEND_SEMAPHORE’ with 10 permits. This semaphore will allow only 10 concurrent calls to the backend system. Java will java virtual threads soon introduce structured concurrency and something called scopes as part of JEP 429, this is quite similar to what Kotlin does in their coroutines. Now let’s look at a similar example, in this case we will use Thread.ofPlatform() and Thread.ofVirtual() to specify what kind of threads we’ll be using in the test.

Virtual Threads in Java (Project Loom)

The framework will invoke that callback on some thread, but not necessarily the same thread that initiated the operation. This means developers must break their logic down into alternating IO and computational steps which are stitched together into a sequential workflow. Java 19 brings the first preview of virtual threads to the Java platform; this is the main deliverable of OpenJDKs Project Loom. This is one of the biggest changes to come to Java in a long time — and at the same time, is an almost imperceptible change. There is almost zero new API surface, and virtual threads behave almost exactly like the threads we already know. Indeed, to use virtual threads effectively, there is more unlearning than learning to be done.