Look at this code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class InvokeAny {
public static void main(String[] args) {
Callable<String> callableTask = () -> {
TimeUnit.MILLISECONDS.sleep(300);
System.out.println("Callable task's execution");
return "Task's execution";
};
List<Callable<String>> callableTasks = new ArrayList<>();
callableTasks.add(callableTask);
callableTasks.add(callableTask);
callableTasks.add(callableTask);
ExecutorService executorService = Executors.newFixedThreadPool(2);
try {
executorService.invokeAny(callableTasks);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
shutdownAndAwaitTermination(executorService);
}
private static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(1000, TimeUnit.MILLISECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(1000, TimeUnit.MILLISECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
}
Every time I run my program, I get different results in console.
1st run:
Callable task's execution
2nd run:
Callable task's execution
Callable task's execution
3rd run:
Callable task's execution
Could anybody explain me why it happens?
In Oracle's documentation there is only one phrase about method invokeAny(Collection<? extends Callable<T>> tasks):
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception), if any do.
I want to understand how it works. Does it cancel remaining tasks after one was completed? If it does, why sometimes I get 2 tasks being executed?