Ответ
В Java 21 в качестве превью-фичи был представлен StructuredTaskScope (JEP 453) – не совсем thread pool, а API для структурированного параллелизма. Он предоставляет более безопасный и управляемый способ запуска и координации групп подзадач (часто выполняемых виртуальными потоками).
Ключевая идея: Задачи, запущенные в одном StructuredTaskScope, должны завершиться до того, как завершится работа самого scope (принцип «Обработка ошибок отменяет зависшие дочерние задачи»).
Пример использования:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// "fork" запускает подзадачи (часто в виртуальных потоках)
Future<String> userTask = scope.fork(() -> fetchUserFromDB());
Future<Integer> orderTask = scope.fork(() -> fetchOrderFromAPI());
scope.join(); // Ожидаем завершения ВСЕХ запущенных подзадач
scope.throwIfFailed(); // Если любая подзадача завершилась с исключением – бросаем его
// Получаем результаты только после успешного join
String user = userTask.resultNow();
Integer order = orderTask.resultNow();
return new Response(user, order);
} // Scope автоматически закрывается, обеспечивая отмену незавершенных задач
Основные преимущества:
- Автоматическое управление жизненным циклом: Задачи ограничены лексической областью видимости (try-with-resources).
- Надежная обработка ошибок: Стратегии
ShutdownOnFailureиShutdownOnSuccessавтоматически отменяют другие задачи при сбое или первом успешном результате. - Упрощение отмены (cancellation): Все дочерние задачи привязаны к сроку жизни родительского scope.
- Идеальная интеграция с Virtual Threads: Эффективно управляет большим количеством легковесных задач.
Ответ 18+ 🔞
А, ну это же та самая штука, где потоки не разбегаются как тараканы, а сидят в своей коробочке, пока ты им не разрешишь! Java 21 подсунула нам StructuredTaskScope – это не очередной thread pool, где сам чёрт ногу сломит, а API для так называемого структурированного параллелизма. Чтоб всё по-порядку было, а не как обычно.
Суть в чём, блядь: Все задачки, запущенные в одном scope, должны хуяк-и готово до того, как сам scope закроется. Принцип железный: если одна сломалась – остальных нахуй отменяем, чтоб не болтались.
Смотри, как это выглядит:
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
// Метод fork – это типа "иди, сделай", обычно на виртуальных потоках
Future<String> userTask = scope.fork(() -> fetchUserFromDB());
Future<Integer> orderTask = scope.fork(() -> fetchOrderFromAPI());
scope.join(); // Сидишь и ждёшь, пока все долбаные подзадачи не упрутся
scope.throwIfFailed(); // Если хоть одна накосячила – тут же летит исключение, всем пиздец
// Только теперь, когда всё чики-пуки, можно результаты выковыривать
String user = userTask.resultNow();
Integer order = orderTask.resultNow();
return new Response(user, order);
} // А тут scope сам закроется и прибьёт всё, что ещё торчит, красота!
А че тут вообще охуенного?
- Жизненный цикл на автомате: Задачи живут строго в рамках try-with-resources, как в клетке. Вышел – всё умерло.
- Ошибки не прокатят: Стратегии
ShutdownOnFailureиShutdownOnSuccessсами решают, кого грохнуть, если одна задача обосралась или, наоборот, уже удачно сделала своё дело. - Отмена – раз плюнуть: Все дочерние задачи – заложники scope. Закрыл scope – всем каюк.
- С виртуальными потоками – просто песня: Идеально, когда этих потоков, блядь, овердохуища, а управлять ими надо как часиками.