0Pricing
Java Academy · Урок

Завершение при сбое и успехе

Координируйте результаты задач

«Завершение при сбое и успехе» — бесплатный урок Java Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Два распространённых шаблона

Большинство параллельных разветвлений относится к одному из двух вариантов:

  • Все должны завершиться успешно: если одна подзадача завершается с ошибкой, остальные прекращаются. Используйте ShutdownOnFailure.
  • Побеждает первая: как только одна подзадача завершается успешно, остальные отменяются. Используйте ShutdownOnSuccess.

JDK предоставляет оба варианта из коробки.

Идея ShutdownOnFailure

ShutdownOnFailure предназначена для задач, которые все должны завершиться успешно, например для совместного получения профиля пользователя и его заказов.

Если одна подзадача выбрасывает исключение, scope отменяет остальные, чтобы не тратить ресурсы впустую.

Пример ShutdownOnFailure

После join() вызывается throwIfFailed(), который повторно выбрасывает первую ошибку, если она произошла, оборачивая её в ExecutionException.

import java.util.concurrent.StructuredTaskScope;

public class Main {
    public static void main(String[] args) throws Exception {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            var a = scope.fork(() -> fetch("profile"));
            var b = scope.fork(() -> fetch("orders"));
            scope.join();
            scope.throwIfFailed();
            System.out.println(a.get() + " + " + b.get());
        }
    }

    static String fetch(String what) {
        return what + "-ok";
    }
}

Что делает throwIfFailed

throwIfFailed() проверяет подзадачи. Если все завершились успешно, он ничего не делает. Если какая-либо завершилась с ошибкой, он выбрасывает исключение, оборачивая исходное исключение.

Также можно передать функцию, преобразующую причину в собственный тип исключения.

Идея ShutdownOnSuccess

ShutdownOnSuccess предназначена для резервирования или гонки: запросите несколько зеркал и возьмите ответившее первым.

В момент успешного завершения одной подзадачи scope отменяет остальные и сохраняет победивший результат.

Пример ShutdownOnSuccess

Победившее значение получают с помощью result(). Этот вызов выбрасывает исключение, если ни одна подзадача не завершилась успешно.

import java.util.concurrent.StructuredTaskScope;

public class Main {
    public static void main(String[] args) throws Exception {
        try (var scope = new StructuredTaskScope.ShutdownOnSuccess<String>()) {
            scope.fork(() -> queryMirror("eu"));
            scope.fork(() -> queryMirror("us"));
            scope.join();
            System.out.println("Fastest answer: " + scope.result());
        }
    }

    static String queryMirror(String region) {
        return region + "-data";
    }
}

Результат против get

Обратите внимание на различие:

  • ShutdownOnFailure: прочитайте каждую подзадачу с помощью собственного get()
  • ShutdownOnSuccess: прочитайте единственного победителя с помощью result() scope

Отмена выполняется согласованно

Когда scope завершает работу, он прерывает потоки оставшихся подзадач. Корректно написанные задачи проверяют факт прерывания и быстро останавливаются.

Блокирующие вызовы стандартной библиотеки обычно автоматически реагируют на прерывание.

join с ограничением времени

Обе политики поддерживают крайний срок. Вызов joinUntil(Instant) ожидает только до определённого момента, затем выбрасывает TimeoutException и завершает работу scope.

Выбор политики

Задайте себе один вопрос: нужны ли мне все результаты или только первый?

  • Все результаты, быстро завершить работу при ошибке: ShutdownOnFailure
  • Любой один результат, побеждает самый быстрый: ShutdownOnSuccess

Для остальных случаев создайте подкласс StructuredTaskScope.

Пользовательские политики

Можно расширить StructuredTaskScope и переопределить handleComplete(Subtask), чтобы реализовать особые правила, например собирать первые N успешных результатов или завершать работу после заданного числа ошибок.

Быстрая проверка

Сопоставьте сценарий с политикой.

Итоги

Вы изучили две встроенные политики завершения:

  • ShutdownOnFailure + throwIfFailed + отдельный get для каждой подзадачи, если все должны завершиться успешно
  • ShutdownOnSuccess + result для варианта, где побеждает первая успешная подзадача
  • Завершение работы согласованно прерывает оставшиеся подзадачи
  • joinUntil добавляет крайние сроки, а создание подкласса — пользовательские правила

Далее: подробное рассмотрение обработки ошибок и отмены.

Часто задаваемые вопросы

Урок «Завершение при сбое и успехе» бесплатный?

Да — полный текст урока «Завершение при сбое и успехе» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Завершение при сбое и успехе»?

Координируйте результаты задач Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Завершение при сбое и успехе»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Модель структурированного параллелизма
  2. StructuredTaskScope
  3. Завершение при сбое и успехе
  4. Обработка ошибок и отмена
← Назад к Java Academy