HowToDoInJava

  • Python
  • Java
  • Spring Boot
  • Dark Mode
Home / Java / Multi-threading / ExecutorService invokeAny()

ExecutorService invokeAny()

Learn to use ExecutorService.invokeAny(tasks) method where we execute multiple tasks at same time, but we make a decision when any one of those tasks is completed and return it’s result.

1. invokeAny() method

This method executes the given list of tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do.

It is an overloaded method. Second method takes timeout parameter and returns before the given timeout elapses whether any task is completed or not.

<T> T 	invokeAny(Collection<? extends Callable<T>> tasks);

<T> T 	invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit);

2. ExecutorService invokeAny() usecases

We can use invokeAny() method in cases where we have various concurrent tasks available to solve a given problem, but we are only interested in the first result. For example,

  • We have multiple array sorting algorithms in application, and we are OK with anyone which sorts fastest and return the sorted array.
  • We have multiple ways to authenticate a user’s identity and we shall return a success response as soon as any one method is successfully able to authenticate the user.

3. ExecutorService invokeAny() example

In this example, we have two ways to authenticate a user’s detail i.e. database and LDAP. We will invoke both methods in separate tasks at same time. As soon as we are able to authenticate user from any given method, we will conclude the user is authenticated.

UserValidator class is template class and based on source value, it connects to either DB or LDAP and validate the user.

import java.util.concurrent.TimeUnit;

public class UserValidator 
{
	private final String source;
	
	public String getSource() {
		return source;
	}

	public UserValidator(String source) {
		this.source = source;
	}

	public boolean validate(String name, String password) 
	{
		//Connect to backend based on source value 
		//and validate the credentials
		
		try {
			long duration = (long) (Math.random() * 10);
			System.out.printf("%s : validating a user in %d seconds\n", this.source, duration);
			TimeUnit.SECONDS.sleep(duration);
		} catch (InterruptedException e) {
			return false;
		}
		return true;
	}
}

UserValidatorTask class represent a validation task which implements Callable interface. Instances of this class can be submitted to executor service to run.

import java.util.concurrent.Callable;

public class UserValidatorTask implements Callable<String> 
{
	private final UserValidator validator;
	private final String user;
	private final String password;

	public UserValidatorTask(UserValidator validator, String user, String password) {
		this.validator = validator;
		this.user = user;
		this.password = password;
	}

	@Override
	public String call() throws Exception {
		if (!validator.validate(user, password)) {
			throw new Exception("Error validating user");
		}
		System.out.printf("%s: The user has been found\n", validator.getSource());
		return validator.getSource();
	}
}

Finally, Main class has the actual logic for creating the validation tasks, submitting to executor service and then validate the first result obtained from any of given two tasks.

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main 
{
	public static void main(String[] args) throws InterruptedException 
	{
		String username = "howtodoinjava";
		String password = "password";
		String result;

		UserValidator ldapValidator = new UserValidator("LDAP");
		UserValidator dbValidator = new UserValidator("DataBase");

		UserValidatorTask ldapTask = new UserValidatorTask(ldapValidator, username, password);
		UserValidatorTask dbTask = new UserValidatorTask(dbValidator, username, password);

		List<UserValidatorTask> taskList = new ArrayList<>();
		taskList.add(ldapTask);
		taskList.add(dbTask);

		ExecutorService executor = (ExecutorService) Executors.newCachedThreadPool();

		try 
		{
			result = executor.invokeAny(taskList);
			System.out.printf("User has been validated from : %s\n", result);
			
			//We may cancel all pending 
                        //tasks after we have our result
			executor.shutdown(); 
		} 
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		} 
		catch (ExecutionException e) {
			e.printStackTrace();
		}
	}
}

Program output.

LDAP : validating a user in 6 seconds
DataBase : validating a user in 3 seconds

DataBase: The user has been found
User has been validated from : DataBase

4. Conclusion

In above example, we learned to execute two callable tasks in executor service. We learned to execute all tasks in one go using invokeAny() method which returns the first available result.

We also saw the usecases where invokeAny() method is pretty useful.

Drop me your questions in comments section.

Happy Learning !!

Was this post helpful?

Let us know if you liked the post. That’s the only way we can improve.

Share this:

  • Twitter
  • Facebook
  • LinkedIn
  • Reddit

About Lokesh Gupta

A family guy with fun loving nature. Love computers, programming and solving everyday problems. Find me on Facebook and Twitter.

Comments are closed on this article!

Search Tutorials

Java Concurrency Tutorial

  • Java Concurrency – Introduction
  • Concurrency Evolution
  • Thread Safety
  • Concurrency vs. Parallelism
  • Compare and Swap [CAS]
  • synchronized keyword
  • Object vs. Class Level Locking
  • Runnable vs. Thread
  • wait(), notify() and notifyAll()
  • Yield() vs. Join()
  • Sleep() vs. Wait()
  • Lock vs. Monitor
  • Callable + Future
  • UncaughtExceptionHandler
  • Throttling Task Submission
  • Executor Best Practices
  • Inter-thread Communication
  • Write and Resolve Deadlock

Java Concurrency Utilities

  • AtomicInteger
  • Lock
  • ThreadFactory
  • ThreadLocal
  • ExecutorService
  • ThreadPoolExecutor
  • FixedSizeThreadPoolExecutor
  • ScheduledThreadPoolExecutor
  • Semaphore
  • Binary Semaphore
  • BlockingQueue
  • DelayQueue
  • ConcurrentLinkedDeque
  • CountDownLatch
  • ForkJoinPool

Java Tutorial

  • Java Introduction
  • Java Keywords
  • Java Flow Control
  • Java OOP
  • Java Inner Class
  • Java String
  • Java Enum
  • Java Collections
  • Java ArrayList
  • Java HashMap
  • Java Array
  • Java Sort
  • Java Clone
  • Java Date Time
  • Java Concurrency
  • Java Generics
  • Java Serialization
  • Java Input Output
  • Java New I/O
  • Java Exceptions
  • Java Annotations
  • Java Reflection
  • Java Garbage collection
  • Java JDBC
  • Java Security
  • Java Regex
  • Java Servlets
  • Java XML
  • Java Puzzles
  • Java Examples
  • Java Libraries
  • Java Resources
  • Java 14
  • Java 12
  • Java 11
  • Java 10
  • Java 9
  • Java 8
  • Java 7

Meta Links

  • About Me
  • Contact Us
  • Privacy policy
  • Advertise
  • Guest and Sponsored Posts

Recommended Reading

  • 10 Life Lessons
  • Secure Hash Algorithms
  • How Web Servers work?
  • How Java I/O Works Internally?
  • Best Way to Learn Java
  • Java Best Practices Guide
  • Microservices Tutorial
  • REST API Tutorial
  • How to Start New Blog

Copyright © 2020 · HowToDoInjava.com · All Rights Reserved. | Sitemap

  • Java 15 New Features
  • Sealed Classes and Interfaces
  • EdDSA (Ed25519 / Ed448)