Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java Concurrency Face-Off: Virtual Threads vs R...

Avatar for A N M Bazlur Rahman A N M Bazlur Rahman
January 01, 2026
5

Java Concurrency Face-Off: Virtual Threads vs Reactive

With virtual threads now in Java, is reactive programming still worth it? This talk compares traditional thread pools, Reactive Streams, and virtual threads by building the same app three ways. We’ll examine performance, memory use, debugging, backpressure, and error handling, then wrap up with a clear decision matrix to help you choose the right concurrency model for your needs.

Avatar for A N M Bazlur Rahman

A N M Bazlur Rahman

January 01, 2026
Tweet

More Decks by A N M Bazlur Rahman

Transcript

  1. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Our Story Begins

    with a Bottleneck 2 • Traditional Java concurrency follows a thread-per-request model. • But threads are expensive, scarce, and mostly wasted due to waiting on I/O. • Threads block on I/O 8090% of the time in typical services
  2. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Two Contenders Emerge

    to Solve This Path 1: Reactive Programming 3 Path 2: Virtual Threads “Donʼt block. Ever. Transform everything into streams.ˮ “What if threads were cheap? Like, really cheap?ˮ A small number of event-loop threads handle many connections by never waiting. Work is scheduled as non-blocking callbacks. Write simple, blocking code. The JVM makes it scalable by parking virtual threads instead of blocking OS threads.
  3. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Reactive Code Flows

    Like a River Through Pipes What It Looks Like 4 Source  filter() map() flatMap() subscribe // Reactive Ingestion Logic public Mono<ProcessingResult> process(Reading reading) { return Mono.zip( repository.save(reading), broadcaster.broadcast(reading), weatherService.fetch(reading.location()) ).flatMap(tuple → { // ... process results from tuple ... }).onErrorResume(ex → { // ... handle error ... }); } Control flow is implicit
  4. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman The Reactive Shift:

    From Occupying Threads to Handling Events This approach is built on three fundamental ideas: 5 Non-Blocking I/O The Foundation Asynchronous Execution: The Mechanism Event-Driven Model: The Architecture
  5. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Pillar 1 Non-Blocking

    IO The thread never blocks waiting for a single connection. It asks the OS for work that is ready “nowˮ and processes it. 6
  6. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Pillar 2 Asynchronous

    Execution 7 Non-Blocking: About not waiting for I/O operations. Asynchronous: About not waiting for a task to complete.
  7. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Pillar 3 The

    Event-Driven Model 8 A pipeline that reacts to the flow of data.
  8. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Virtual Threads with

    Structured Concurrency // Imperative, sequential code try (var scope = StructuredTaskScope.open()) { scope.fork(() -> repo.save(r)); scope.fork(() -> broadcast(r)); scope.fork(() -> weather(loc)); scope.join(); } 12
  9. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Two Paths to

    Scalability Reactive (WebFlux) Virtual Threads (Loom) 13 • “Donʼt Blockˮ Philosophy • Asynchronous & Non-Blocking • Event-loop based scheduling • Power through Operators • “Blocking is Fineˮ Philosophy • Synchronous code, non-blocking runtime • Lightweight, JVM-managed threads • Simplicity through Imperative Code
  10. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman The Arena: A

    Fair Fight in the HIVE A thermostat monitoring system that ingests sensor data, enriches it with external weather data, persists it to a database, and streams updates to a live dashboard via Server-Sent Events SSE. The Rules of Engagement • Identical Functionality: Same API surface, same database schema, same business logic. • Equivalent Environments: Deployed in identical containers with the same CPU 4 cores) and memory 2G) limits. • Shared Dependencies: Both use the same PostgreSQL database and simulated external services. 15
  11. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman The Debugging Experience

    - Reactive 16 Your applicationʼs story is buried in the frameworkʼs mechanics.
  12. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman The Debugging Experience

    - Virtual Threads 17 The stack trace reads exactly like your code is written.
  13. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Round 4 The

    Operational Reality 21 Scores reflect developer experience (subjective) in this case study, not universal truth.
  14. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman “Observability cost shows

    up at 3 AM, not in benchmarks.“ Truth be told… 22
  15. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Performance + Operability:

    What Actually Matters in Production What benchmarks tell us • Average and tail latency (p95 / p99 • Throughput under load • Resource utilization • Error rates What operations demand • Clear causal stack traces • Errors mapped to business flow • Predictable failure boundaries • Fast root-cause analysis under pressure 23 Necessary, measurable, repeatable Inevitable, human, time-critical Numbers describe symptoms. Operability determines how fast you find causes.
  16. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman Backpressure: Where Control

    Lives 24 Reactive frameworks provide first-class backpressure. Virtual threads require explicit backpressure strategies.
  17. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman ? Which model

    do you prefer for your next service? Reactive? or Virtual Threads? 25
  18. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman The Right Tool

    for the Job Choose Virtual Threads When: • Building typical I/O-bound services REST APIs, CRUD apps). • Prioritizing simple, maintainable code and easy debugging. • Migrating an existing blocking application for better scalability. 26 Consider Reactive When: • Your logic is fundamentally a stream of events (e.g., Kafka processing, UI event handling). • You require fine-grained, built-in backpressure control. • You are working within an existing, mature Reactive ecosystem.
  19. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman “The best code

    is the code you can understand six months from now at 3 AM during an outage.ˮ — Every On-Call Engineer, Ever Ultimately 27
  20. https://bazlur.ca A N M Bazlur Rahman @bazlur_rahman A N M

    Bazlur Rahman 28 Java Champion · Sr. Staff Software Engineer · Author of Modern Concurrency in Java · InfoQ Editor https://x.com/bazlur_rahman rokon12 https://www.linkedin.com/in/bazlur/ https://bazlur.ca/ https://bsky.app/profile/bazlur.ca