StructuredTaskScope
Запускайте подзадачи и объединяйте их результаты
«StructuredTaskScope» — бесплатный урок Java Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.
Знакомство с StructuredTaskScope
StructuredTaskScope — основной программный интерфейс структурированного параллелизма. Вы открываете scope, создаёте подзадачи с помощью fork, вызываете join, чтобы дождаться их завершения, а затем читаете результаты.
Это функция предварительного просмотра, поэтому компилируйте и запускайте программу с --enable-preview.
Основной жизненный цикл
Каждое использование следует одному и тому же ритму из четырёх шагов:
- Откройте scope в блоке try с ресурсами
- Создайте с помощью
forkодну или несколько подзадач, каждая из которых возвращает дескрипторSubtask - Вызовите
join, чтобы дождаться завершения - Прочитайте результат каждой подзадачи через
get()
Fork возвращает дескриптор
fork(Callable) немедленно запускает подзадачу в виртуальном потоке и возвращает объект Subtask. Нельзя вызывать его get(), пока не вернётся join().
Полный пример
Здесь две подзадачи выполняются параллельно. Обе должны завершиться до того, как мы прочитаем результаты. Используется ShutdownOnFailure — встроенная политика.
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
var name = scope.fork(() -> "Grace");
var count = scope.fork(() -> 3);
scope.join();
scope.throwIfFailed();
System.out.println(name.get() + " placed " + count.get() + " orders");
}
}
}Сначала join, затем get
Порядок вызовов строго определён: fork, затем join, затем get. Вызов get() для подзадачи до завершения join() приводит к исключению IllegalStateException.
Именно это правило сохраняет структурированное время жизни.
Состояния подзадачи
После join() каждая подзадача сообщает своё state():
SUCCESSс результатом изget()FAILEDс исключением изexception()UNAVAILABLE, если она так и не завершилась
Множество подзадач
Вы можете создавать сколько угодно подзадач; каждая получает собственный виртуальный поток. Так выполняется разветвление пакета независимых вызовов.
import java.util.*;
import java.util.concurrent.StructuredTaskScope;
public class Main {
public static void main(String[] args) throws Exception {
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
List<StructuredTaskScope.Subtask<Integer>> tasks = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
final int n = i;
tasks.add(scope.fork(() -> n * n));
}
scope.join();
scope.throwIfFailed();
int total = tasks.stream().mapToInt(StructuredTaskScope.Subtask::get).sum();
System.out.println("Sum of squares 1..5 = " + total);
}
}
}scope владеет потоками
scope реализует AutoCloseable. Когда блок try завершается, close() гарантирует завершение каждого потока подзадачи. Утечки невозможны.
Поэтому его всегда используют внутри блока try с ресурсами.
Встроенные политики
JDK поставляется с двумя готовыми политиками завершения:
ShutdownOnFailure: отменить остальные подзадачи, если какая-либо подзадача завершилась с ошибкойShutdownOnSuccess: отменить остальные подзадачи после успешного завершения одной из них
Также можно создать подкласс StructuredTaskScope для реализации собственной логики.
Вызов join из того же потока
Только поток, открывший scope, может создавать в нём подзадачи и вызывать join. Подзадачи принадлежат своему scope, что сохраняет корректную структуру дерева.
Флаги компиляции и запуска
Поскольку этот программный интерфейс является функцией предварительного просмотра, собирайте программу с помощью:
javac --release 21 --enable-preview Main.javajava --enable-preview Main
Без этого флага возникает ошибка компиляции или выполнения.
Быстрая проверка
Вспомните обязательный порядок вызовов.
Итоги
Вы изучили программный интерфейс StructuredTaskScope:
- Открыть в блоке try с ресурсами, выполнить
fork,join, а затемget - Каждая подзадача выполняется в собственном виртуальном потоке
- scope гарантирует завершение всех подзадач до закрытия
- Требуется
--enable-preview
Далее: подробное изучение политик завершения при ошибке и при успехе.
Часто задаваемые вопросы
Урок «StructuredTaskScope» бесплатный?
Да — полный текст урока «StructuredTaskScope» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.
Чему я научусь в уроке «StructuredTaskScope»?
Запускайте подзадачи и объединяйте их результаты Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Java Academy?
Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «StructuredTaskScope»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Java Academy?
Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Модель структурированного параллелизма
- StructuredTaskScope
- Завершение при сбое и успехе
- Обработка ошибок и отмена