An event loop thread, also called an I/O thread, handles concurrent I/O without assigning a new thread to every request. While an operation waits for I/O, the thread can serve other work. In Quarkus, this nonblocking model uses a reactive engine based on Vert.x and Netty; using fewer threads can reduce memory and CPU consumption in cloud workloads. section 8.1.1 section 8.7
Figure 8.2 Nonblocking I/O request handling: threads don’t block while waiting for an I/O operation to complete
The diagram contrasts waiting for I/O with letting a thread handle other work until the operation completes. section 8.1.1
The essential constraint is not to block the event loop. Quarkus logs a warning when a thread remains blocked beyond its configured limit, which is two seconds by default; some recognized blocking operations fail immediately. Work that must block belongs on a worker thread instead. section 8.1.1
Quarkus chooses where a method runs, but the choice must match what the method actually does:
- A method returning a reactive, nonblocking type normally runs on an event loop thread; other return types normally run on a worker thread. section 8.1.1
- Use @Blocking when a method must perform blocking work, even if its signature returns a reactive type. @NonBlocking indicates work intended for the event loop. section 8.1.1 section 8.4.2
Reservation persistence without occupying the I/O thread
A REST method can return a Mutiny Uni from a reactive database persist operation. The I/O thread starts the request and becomes available while the database works. An onItem callback continues processing when the result arrives; it may run on a different event loop thread. section 8.4.1
A reactive signature with blocking work
An inventory gRPC method returns a Multi but performs blocking database inserts in its pipeline. Its @Blocking annotation directs that work away from the event loop; a reactive return type alone does not make the database operation nonblocking. section 8.4.2
