Метод invokeAll
Метод invokeAll класса ExecutorService
принимает коллекцию задач типа Callable,
запускает их все на выполнение и блокирует
текущий поток до тех пор, пока все задачи
не завершатся. Метод возвращает список объектов
Future в том же порядке, в котором задачи
были переданы в коллекции. В первый параметр
мы передаем коллекцию задач, во второй
(необязательный) - таймаут ожидания,
в третий (необязательный) - единицу измерения
этого таймаута.
Существует две перегрузки метода: одна принимает только коллекцию задач и ждет их завершения бесконечно, вторая принимает таймаут и по его истечении отменяет незавершенные задачи.
Синтаксис
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
Пример
Давайте создадим пул из двух потоков и запустим три задачи, каждая из которых возвращает удвоенное значение своего аргумента:
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(2);
List<Callable<Integer>> tasks = List.of(
() -> 1 * 2,
() -> 2 * 2,
() -> 3 * 2
);
List<Future<Integer>> futures = executor.invokeAll(tasks);
for (Future<Integer> future : futures) {
System.out.println(future.get());
}
executor.shutdown();
}
}
Результат выполнения кода:
2
4
6
Пример
Давайте передадим задачи, возвращающие строки, и выведем результаты в том же порядке, в котором задачи были добавлены в список:
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Callable<String>> tasks = List.of(
() -> "abcde",
() -> "12345",
() -> "abcde12345"
);
List<Future<String>> futures = executor.invokeAll(tasks);
for (Future<String> future : futures) {
System.out.println(future.get());
}
executor.shutdown();
}
}
Результат выполнения кода:
"abcde"
"12345"
"abcde12345"
Пример
Давайте используем перегрузку с таймаутом:
если задача не успевает выполниться за указанное
время, соответствующая Future будет отменена.
Проверим статус отмены через isCancelled:
import java.util.List;
import java.util.concurrent.Callable;
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 Exception
{
ExecutorService executor = Executors.newFixedThreadPool(1);
List<Callable<String>> tasks = List.of(
() -> "abcde",
() -> {
Thread.sleep(5000);
return "12345";
}
);
List<Future<String>> futures = executor.invokeAll(tasks, 1, TimeUnit.SECONDS);
for (Future<String> future : futures) {
if (future.isCancelled()) {
System.out.println("cancelled");
} else {
System.out.println(future.get());
}
}
executor.shutdown();
}
}
Результат выполнения кода:
"abcde"
"cancelled"
Смотрите также
-
класс
ExecutorService,
который управляет пулом потоков -
метод
submit,
который запускает одну задачу и возвращает Future -
метод
invokeAny,
который возвращает результат первой завершенной задачи -
метод
shutdown,
который завершает работу пула потоков