January 8, 2023 ExecutorService invokeAny() Learn to use ExecutorService.invokeAny(tasks) method where we execute multiple tasks at the same time, but we make a decision when any one of those tasks is completed and return its 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. The second method takes a 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 = "howtostartprogramming"; 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 Concurrency Java data safetyhow to use spring bootibm websphere (software)ibm websphere application server (software)java multi threadinglambda expression in rest assured frameworklearn microservicesmultithreadingpredicate lambda expressionred hat enterprise linuxresponseentityrestful architecturespring boot microservicesspring boot rest apispring boot securityspring boot tutorialspring boot tutorial for beginnersweb development (interest)