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
