Научитесь запускать несколько задач Callable с помощью API ExecutorService.invokeAll() и обрабатывать все результаты, возвращаемые задачами, в виде экземпляров класса Future в этом примере ExecutorService Callable.
1. API ExecutorService invokeAll()
Метод invokeAll() выполняет указанный список вызываемых задач, возвращая список объектов Future, содержащих их статус и результаты, когда все они будут завершены.
Это перегруженный метод, который существует в двух формах. Второй метод принимает дополнительные параметры, обозначающие тайм-аут. Класс TimeUnit — это перечисление со следующими константами: ДНИ, ЧАСЫ, МИКРОСЕКУНЫ, МИЛЛИСЕКУНДЫ, МИНУТЫ, НАНОСЕКУНДЫ и СЕКУНДЫ.
/*** @param - tasks - the collection of tasks* @return - a list of Futures representing the tasks, in the same* sequential order as produced by the iterator for the* given task list.*/<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)/*** @param - tasks - the collection of tasks* @param - timeout - the maximum time to wait* @param - unit - the time unit of the timeout argument* @return - a list of Futures representing the tasks, in the same* sequential order as produced by the iterator for the* given task list.*/<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
Важно отметить, что первым объектом в списке объектов Future будет объект, который управляет первой задачей в списке объектов Callable, вторым объектом — второй задачей и т. д.
2. Пример ExecutorService invokeAll()
В этом примере мы создаем демонстрационную задачу, которая ничего не делает, а только печатает некоторые утверждения. Это не для того, чтобы вносить какую-либо сложность и сосредоточиться на основной концепции.
class Task implements Callable<Result>{private final String name;public Task(String name) {this.name = name;}@Overridepublic Result call() throws Exception{System.out.printf("%s: Staring\n", this.name);try {long duration =(long)(Math.random() * 10);System.out.printf("%s: Waiting %d seconds for results.\n", this.name, duration);TimeUnit.SECONDS.sleep(duration);} catch(InterruptedException e) {e.printStackTrace();}return new Result(this.name, LocalDateTime.now().toString());}}
Аналогично мы собираем результат после выполнения задачи в классе Result, который хранит имя задачи и временную метку ее завершения.
class Result{private String name;private String timestamp;public Result(String name, String timestamp) {super();this.name = name;this.timestamp = timestamp;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getTimestamp() {return timestamp;}public void setTimestamp(String timestamp) {this.timestamp = timestamp;}@Overridepublic String toString() {return "Result [name=" + name + ", value=" + timestamp + "]";}}
В этом примере мы отправили 5 задач, которые отправляются в службу исполнителя с помощью метода invokeAll(). Все задачи выполняются в разное время, поскольку в пуле потоков находится только два потока.
import java.time.LocalDateTime;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.TimeUnit;public class Main{public static void main(String[] args) throws InterruptedException{ExecutorService executor =(ExecutorService) Executors.newFixedThreadPool(2);List<Task> taskList = new ArrayList<>();for(int i = 0; i < 5; i++) {Task task = new Task("Task-" + i);taskList.add(task);}//Execute all tasks and get reference to Future objectsList<Future<Result>> resultList = null;try {resultList = executor.invokeAll(taskList);} catch(InterruptedException e) {e.printStackTrace();}executor.shutdown();System.out.println("\n========Printing the results======");for(int i = 0; i < resultList.size(); i++) {Future<Result> future = resultList.get(i);try {Result result = future.get();System.out.println(result.getName() + ": " + result.getTimestamp());} catch(InterruptedException | ExecutionException e) {e.printStackTrace();}}}}
Вывод программы.
Task-0: StaringTask-0: Waiting 7 seconds for results.Task-1: StaringTask-1: Waiting 1 seconds for results.Task-2: StaringTask-2: Waiting 2 seconds for results.Task-3: StaringTask-3: Waiting 3 seconds for results.Task-4: StaringTask-4: Waiting 4 seconds for results.========Printing the results======Task-0: 2019-05-23T12:56:33.692Task-1: 2019-05-23T12:56:27.885Task-2: 2019-05-23T12:56:29.887Task-3: 2019-05-23T12:56:32.889Task-4: 2019-05-23T12:56:36.890
Главное, что следует отметить, это то, что даже если выполнено несколько задач, программа не начинает печатать результаты. Результат мы получаем только после того, как выполнены все задачи.
Напишите мне в разделе комментариев ваши вопросы, связанные с примером вызова Java ExecutorService.