Java / Java 21 Interview Questions
How do virtual threads compare to reactive programming (Project Reactor / RxJava)?
Both virtual threads (Java 21) and reactive frameworks solve the same underlying problem: how to serve many concurrent I/O-bound requests without blocking OS threads, which are expensive. They solve it very differently.
| Aspect | Reactive (Reactor/RxJava) | Virtual Threads (Java 21) |
|---|---|---|
| Programming style | Functional/async chains (flatMap, subscribe) | Imperative blocking code |
| Debugging | Complex — callbacks and stack traces are fragmented | Simple — full stack traces, works with standard debugger |
| Library compatibility | Requires reactive-aware libs (R2DBC, WebFlux) | Works with any blocking library (JDBC, HttpClient) |
| Error handling | onError / catch in chains | Normal try/catch |
| Learning curve | High — new mental model | Low — reads like sequential code |
| Context propagation | Manual (reactor Context) | ThreadLocal (or ScopedValue) |
| CPU-bound work | No advantage | No advantage — still needs ForkJoinPool |
// Reactive style (Spring WebFlux)
Mono result = userRepository.findById(id) // Mono
.flatMap(user -> orderRepository.findByUser(user.id())) // Mono
.map(order -> order.summary())
.onErrorReturn("default response");
// Virtual thread style (Spring Boot 3.2+ with Tomcat virtual threads)
String result;
try {
User user = userRepository.findById(id); // blocking — parks VT
Order order = orderRepository.findByUser(user.id()); // same
result = order.summary();
} catch (Exception e) {
result = "default response";
}
// Spring Boot 3.2 — enable virtual threads for Tomcat:
// spring.threads.virtual.enabled=true
// All @RequestMapping handlers run on virtual threads automatically The consensus in the Java community for Java 21+: prefer virtual threads for new applications — the code is simpler, debuggable, and compatible with the existing JDBC/HTTP ecosystem. Reactive programming remains justified when you need fine-grained back-pressure, stream operators for event pipelines, or when integrating with reactive middleware that does not have a blocking API.
More Related questions...