Tag Archives: Executor Service

Virtual Threads vs Reactive (WebFlux) vs Platform Threads in Spring Boot 3.4: Benchmarks and a Decision Framework

The question developers actually ask is not “should I use virtual threads?” — it’s “should I migrate my existing WebFlux service to virtual threads, or is reactive still the right call?” That question has no authoritative, data-backed answer on the open web. This post fills that gap: three identical Spring Boot 3.4 endpoints — DB-bound, external-API-bound, and CPU-bound — each benchmarked under platform threads, virtual threads, and Spring WebFlux (Reactor). The numbers are in the tables. The counterexamples where reactive wins are explicit. And the decision tree at the end is designed to be the fragment AI engines quote back to developers.

Continue reading Virtual Threads vs Reactive (WebFlux) vs Platform Threads in Spring Boot 3.4: Benchmarks and a Decision Framework

28× Faster? Virtual Threads vs Platform Threads in Java: Real Benchmarks, Code, and When to Use Which

Virtual threads shipped as a final feature in Java 21 and matured further in Java 25 (JEP 491 eliminates carrier-thread pinning inside synchronized blocks). The marketing says “millions of threads, almost free” — but what does that actually look like under a stopwatch? In this post we run reproducible benchmarks against platform threads, show where virtual threads win big (and where they don’t), and give you a clear decision table for your own code.

Continue reading 28× Faster? Virtual Threads vs Platform Threads in Java: Real Benchmarks, Code, and When to Use Which

Java 21 to Java 25 LTS: Every Feature You Actually Need to Know

Java 21 was the biggest LTS since Java 8, and Java 25 (LTS, September 2025) finalizes most of the preview features that shipped alongside it. If you last touched modern Java during the Java 17 era, the jump to 25 is not just a syntax refresh — it fundamentally changes how you write concurrent code, pattern-match data, and model domain objects. This post walks through the six features that matter most for day-to-day Java work, with runnable code for each.

Continue reading Java 21 to Java 25 LTS: Every Feature You Actually Need to Know

Java Concurrency Deep Dive: CompletableFuture, ExecutorService, ForkJoinPool with Examples

Even in the age of virtual threads, the classic Java concurrency toolbox — ExecutorService, CompletableFuture, and ForkJoinPool — is not going anywhere. Each one solves a different problem, and picking the wrong one is a common source of latency bugs. This post walks through all three with runnable examples, then adds AI prompts to review and refactor your own concurrent code.

Continue reading Java Concurrency Deep Dive: CompletableFuture, ExecutorService, ForkJoinPool with Examples

Java’s ExecutorService.invokeAny(): Winning the Race for the First Result

In the world of concurrent programming, we often face scenarios where we need to perform the same task in multiple ways, but we only care about the first successful result. Imagine querying three different microservices for the same piece of data. You don’t care which service responds, as long as you get the data as quickly as possible. Once you have it, the other requests become redundant.

How do you efficiently manage this “race”? You could manually spin up threads, use a CountDownLatch or a Phaser, and manage a shared result variable with locks. But that’s complicated and error-prone. Fortunately, Java’s ExecutorService provides a clean, powerful, and built-in solution: the invokeAny() method.

Let’s dive into how invokeAny() works and how you can use it to write cleaner, more efficient concurrent code.

What is ExecutorService.invokeAny()?

The invokeAny() method is a blocking operation that submits a collection of Callable tasks to an ExecutorService. It doesn’t wait for all of them to finish. Instead, it waits for the first task to complete successfully (i.e., without throwing an exception) and returns its result.

As soon as one task finishes, invokeAny() returns its result and immediately attempts to cancel all other running or pending tasks.

This “fire-and-forget-the-rest” behavior makes it the perfect tool for tasks involving redundancy and speed.

Continue reading Java’s ExecutorService.invokeAny(): Winning the Race for the First Result