Практика на исполнители задач в Java
Сервис сводок считает три показателя независимо и отдаёт
их списком вызывающему коду. Вынесем расчёты в
Callable и поручим их общему пулу.
Класс хранит размер пула и умеет собирать пакет метрик:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
class ReportService {
private final ExecutorService pool;
ReportService(int threads) {
pool = Executors.newFixedThreadPool(threads);
}
List<Integer> loadAll() throws Exception {
List<Callable<Integer>> jobs = List.of(
() -> 12 + 8,
() -> 100 / 5,
() -> 7 * 6
);
List<Future<Integer>> done = pool.invokeAll(jobs);
List<Integer> out = new ArrayList<>();
for (Future<Integer> slot : done) {
out.add(slot.get());
}
return out;
}
void close() {
pool.shutdown();
}
}
В main создаём сервис, читаем сводку и закрываем
пул:
public class Main {
public static void main(String[] args) throws Exception {
ReportService service = new ReportService(2);
try {
System.out.println(service.loadAll());
} finally {
service.close();
}
}
}
На экране список из трёх чисел в порядке задач. Пул из
двух потоков может выполнять часть работы параллельно,
но invokeAll всё равно вернёт управление только
когда готов весь набор.
Добавьте четвёртую задачу, возвращающую сумму
1 + 2 + 3 + 4. Убедитесь, что список содержит
4 элемента и последний равен 10.
Перепишите закрытие сервиса: пусть ReportService
реализует AutoCloseable и в close()
вызывает shutdown с ожиданием не более
5 секунд.