0Pricing
Java Academy · Lekcja

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 obiektu ThreadFactory
  • Executors.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

  1. Czym są wirtualne wątki
  2. Tworzenie wirtualnych wątków
  3. Wątki platformowe a wirtualne
  4. Pułapki: przypinanie i ThreadLocal
← Powrót do Java Academy