Какой новый механизм для управления пулами потоков (Thread Pool) появился в Java 21?

Ответ

В 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 – всем каюк.
  • С виртуальными потоками – просто песня: Идеально, когда этих потоков, блядь, овердохуища, а управлять ими надо как часиками.