StructuredTaskScope
Rozgałęzianie i łączenie podzadań
StructuredTaskScope to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.
Poznaj StructuredTaskScope
StructuredTaskScope to podstawowe API współbieżności strukturalnej. Zakres jest otwierany, podzadania uruchamiane za pomocą fork, następnie wywoływany jest join, aby na nie zaczekać, a potem odczytywane są ich wyniki.
Jest to funkcja w wersji preview, dlatego program należy kompilować i uruchamiać z użyciem --enable-preview.
Podstawowy cykl życia
Każde użycie przebiega według tego samego czterostopniowego schematu:
- Otworzyć zakres w bloku try-with-resources
- Wywołać
forkdla co najmniej jednego podzadania, z których każde zwraca uchwytSubtask - Wywołać
join, aby zaczekać na zakończenie - Odczytać wynik każdego podzadania za pomocą
get()
fork zwraca uchwyt
fork(Callable) natychmiast uruchamia podzadanie na wirtualnym wątku i zwraca obiekt Subtask. Nie wolno wywoływać jego get() przed zakończeniem działania join().
Kompletny przykład
W tym przykładzie dwa podzadania działają współbieżnie. Oba muszą się zakończyć, zanim odczytamy wyniki. Wykorzystano wbudowaną zasadę 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, a następnie odczyt
Reguła kolejności jest ścisła: fork, następnie join, a potem get. Wywołanie get() na podzadaniu przed zakończeniem join() powoduje zgłoszenie wyjątku IllegalStateException.
To ta reguła zapewnia uporządkowany cykl życia.
Stany podzadań
Po wywołaniu join() każde podzadanie Subtask zgłasza stan za pomocą state():
SUCCESSz wynikiem dostępnym przezget()FAILEDz wyjątkiem dostępnym przezexception()UNAVAILABLE, jeśli podzadanie nigdy nie zostało ukończone
Wiele podzadań
Można wywołać fork dla dowolnej liczby podzadań; każde otrzyma własny wątek wirtualny. W ten sposób rozdziela się partię niezależnych wywołań na wiele zadań.
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);
}
}
}Zakres zarządza wątkami
Zakres jest obiektem AutoCloseable. Gdy kończy się blok try, metoda close() gwarantuje, że każdy wątek podzadania zakończył działanie. Wycieki są niemożliwe.
Dlatego zawsze należy używać zakresu wewnątrz bloku try-with-resources.
Wbudowane zasady
JDK dostarcza dwie gotowe zasady zamykania:
ShutdownOnFailure: anulowanie pozostałych podzadań, jeśli którekolwiek zakończy się niepowodzeniemShutdownOnSuccess: anulowanie pozostałych podzadań, gdy którekolwiek zakończy się powodzeniem
Można także utworzyć podklasę StructuredTaskScope, aby zaimplementować własną logikę.
join z tego samego wątku
Tylko wątek, który otworzył zakres, może wywoływać w nim fork i join. Podzadania są ograniczone do należącego do nich zakresu, co zapewnia poprawną strukturę drzewa.
Flagi kompilacji i uruchamiania
Ponieważ API jest funkcją w wersji preview, należy kompilować za pomocą:
javac --release 21 --enable-preview Main.javajava --enable-preview Main
Bez tej flagi pojawi się błąd kompilacji lub uruchamiania.
Szybkie sprawdzenie
Proszę przypomnieć sobie obowiązkową kolejność wywołań.
Podsumowanie
Poznali Państwo API StructuredTaskScope:
- Otwieranie w try-with-resources, następnie
fork,joiniget - Każde podzadanie działa na własnym wątku wirtualnym
- Zakres gwarantuje zakończenie wszystkich podzadań przed zamknięciem
- Wymaga
--enable-preview
Następnie: szczegółowe omówienie zasad zamykania po niepowodzeniu i po powodzeniu.
Często zadawane pytania
Czy lekcja „StructuredTaskScope” jest bezpłatna?
Tak — pełny tekst „StructuredTaskScope” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „StructuredTaskScope”?
Rozgałęzianie i łączenie podzadań Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Java Academy?
Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „StructuredTaskScope”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?
Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Model współbieżności strukturalnej
- StructuredTaskScope
- Zamykanie po błędzie i powodzeniu
- Obsługa błędów i anulowanie