Tworzenie wirtualnych wątków
Thread.ofVirtual i executory
Tworzenie wirtualnych wątków 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.
Sposoby tworzenia wątków wirtualnych
Java oferuje kilka sposobów tworzenia wątków wirtualnych. Dwa najważniejsze to kreator Thread.ofVirtual() oraz fabryka Executors.newVirtualThreadPerTaskExecutor().
W tej lekcji omówimy każdy z nich.
Kreator: start
Thread.ofVirtual() zwraca kreator. Wywołanie .start(runnable) tworzy wątek i natychmiast go uruchamia.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().start(() ->
System.out.println("Started directly"));
t.join();
}
}Kreator: unstarted
Metody .unstarted(runnable) należy użyć, gdy chcą Państwo skonfigurować wątek i uruchomić go później.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.ofVirtual().unstarted(() ->
System.out.println("Started later"));
System.out.println("Before start, alive? " + t.isAlive());
t.start();
t.join();
}
}Fabryka wielokrotnego użytku
Kreator może za pomocą .factory() utworzyć obiekt ThreadFactory. Każde wywołanie newThread zwraca nowy wątek wirtualny.
import java.util.concurrent.ThreadFactory;
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadFactory factory = Thread.ofVirtual().name("job-", 0).factory();
Thread a = factory.newThread(() ->
System.out.println(Thread.currentThread().getName()));
Thread b = factory.newThread(() ->
System.out.println(Thread.currentThread().getName()));
a.start(); b.start();
a.join(); b.join();
}
}Metoda pomocnicza
Thread.startVirtualThread(runnable) to skrócony zapis, który w jednym wywołaniu tworzy i uruchamia nienazwany wątek wirtualny.
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = Thread.startVirtualThread(() ->
System.out.println("One-liner virtual thread"));
t.join();
}
}Podejście z użyciem executora
W kodzie zorientowanym na zadania warto użyć Executors.newVirtualThreadPerTaskExecutor(). Tworzy on nowy wątek wirtualny dla każdego przesłanego zadania.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
exec.submit(() -> System.out.println("task one"));
exec.submit(() -> System.out.println("task two"));
}
System.out.println("All tasks submitted and completed");
}
}Dlaczego warto używać try-with-resources
Od Java 19 interfejs ExecutorService implementuje AutoCloseable. Zamknięcie go w bloku try-with-resources powoduje oczekiwanie na ukończenie wszystkich przesłanych zadań.
Zapewnia to uporządkowane zamykanie bez konieczności ręcznego wywoływania metod shutdown i awaitTermination.
Przesyłanie wielu zadań
Executor tworzący wątek dla każdego zadania bez trudu obsługuje ogromną liczbę zadań. Każde zadanie otrzymuje własny wątek wirtualny.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) {
AtomicInteger sum = new AtomicInteger();
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 1; i <= 1000; i++) {
final int n = i;
exec.submit(() -> sum.addAndGet(n));
}
}
System.out.println("Sum 1..1000 = " + sum.get());
}
}Zbieranie wyników za pomocą Future
submit zwraca obiekt Future, dzięki czemu można zbierać wartości zwracane tak samo jak w przypadku dowolnego executora.
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
Future<Integer> f = exec.submit(() -> 6 * 7);
System.out.println("Result: " + f.get());
}
}
}Kreator czy executor
Wyboru należy dokonać w zależności od celu:
- Builder / startVirtualThread w przypadku jednorazowych wątków lub niestandardowego nazewnictwa
- newVirtualThreadPerTaskExecutor w przypadku przesyłania kolekcji zadań i zbierania wyników
Oba rozwiązania tworzą jeden wątek wirtualny dla każdej jednostki pracy — dokładnie tego Państwo potrzebują.
Nigdy nie buforuj executora wątków wirtualnych
Nie należy ponownie używać jednego executora wątków wirtualnych tak, jakby był stałą pulą wątków roboczych. Sam executor można ponownie wykorzystywać, ale należy pamiętać, że każde zadanie tworzy zupełnie nowy wątek.
Chodzi o to, że nie ma tu puli wątków, a jedynie wygodny mechanizm przesyłania zadań.
Szybkie sprawdzenie
Wybierz najlepszy sposób uruchomienia dużej partii zadań, z których każde ma działać we własnym wątku wirtualnym.
Podsumowanie
Wiedzą już Państwo, jak tworzyć wątki wirtualne:
Thread.ofVirtual().start(...)i.unstarted(...)- Jednolinijkowy zapis
Thread.startVirtualThread(...) .factory()do tworzenia wielokrotnego użytku obiektuThreadFactoryExecutors.newVirtualThreadPerTaskExecutor()w połączeniu z try-with-resources
W następnej części: wybór między wątkami platformowymi a wirtualnymi.
Często zadawane pytania
Czy lekcja „Tworzenie wirtualnych wątków” jest bezpłatna?
Tak — pełny tekst „Tworzenie wirtualnych wątków” 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 „Tworzenie wirtualnych wątków”?
Thread.ofVirtual i executory Ć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 „Tworzenie wirtualnych wątków”?
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
- Czym są wirtualne wątki
- Tworzenie wirtualnych wątków
- Wątki platformowe a wirtualne
- Pułapki: przypinanie i ThreadLocal