0Pricing
Learn Rust Coding · Lekcja

Uruchamianie wątków

Uruchomi Pan/Pani kod współbieżnie.

Uruchamianie wątków to bezpłatna lekcja Learn Rust Coding na CoddyKit. To lekcja 1 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 Learn Rust Coding, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.

Czym jest wątek?

Wątek pozwala programowi wykonywać kod współbieżnie. System operacyjny może planować działanie wielu wątków, dzięki czemu ich praca może przebiegać nakładająco.

Biblioteka standardowa Rusta udostępnia wątki za pośrednictwem modułu std::thread. Są to natywne wątki systemu operacyjnego, nazywane czasem wątkami 1:1.

W tej lekcji nauczy się Pan/Pani uruchamiać nowe wątki i sterować ich działaniem.

Tworzenie wątku za pomocą thread::spawn

Nowy wątek tworzy się przez wywołanie thread::spawn i przekazanie mu domknięcia. Domknięcie zawiera kod, który wykona nowy wątek.

Wywołanie natychmiast zwraca obiekt JoinHandle, a utworzony wątek działa w tle.

use std::thread;

fn main() {
    thread::spawn(|| {
        println!("hello from a thread");
    });
    println!("hello from main");
}

Wątek główny może zakończyć się pierwszy

Gdy funkcja main zwraca wartość, cały proces kończy działanie, nawet jeśli utworzone wątki nadal pracują.

Dlatego powyższy program może wypisać tylko komunikat wątku głównego. Wątek działający w tle może nie zdążyć rozpocząć pracy przed zakończeniem procesu.

Potrzebny jest sposób oczekiwania na zakończenie wątków.

Oczekiwanie za pomocą join

Obiekt JoinHandle zwrócony przez spawn ma metodę join. Jej wywołanie blokuje bieżący wątek do momentu zakończenia utworzonego wątku.

Gwarantuje to, że utworzony wątek zakończy działanie, zanim wątek główny będzie kontynuować pracę.

use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        println!("worker done");
    });
    handle.join().unwrap();
    println!("main done");
}

Przeplatanie danych wyjściowych

Gdy dwa wątki działają jednocześnie, ich dane wyjściowe mogą przeplatać się w nieprzewidywalny sposób. Harmonogram ustala system operacyjny.

Dwukrotne uruchomienie tego samego programu może dać różną kolejność wyników. Bez synchronizacji nigdy nie należy polegać na określonej kolejności.

use std::thread;

fn main() {
    let handle = thread::spawn(|| {
        for i in 1..4 {
            println!("thread: {}", i);
        }
    });
    for i in 1..4 {
        println!("main: {}", i);
    }
    handle.join().unwrap();
}

Wstrzymywanie za pomocą sleep

Wątek można wstrzymać za pomocą thread::sleep, które przyjmuje wartość typu Duration. Zwalnia to procesor, aby inne wątki mogły kontynuować pracę.

Usypianie jest przydatne w przykładach, aby wyraźniej pokazać przeplatanie, ale nie należy używać go do rzeczywistej synchronizacji.

use std::thread;
use std::time::Duration;

fn main() {
    thread::spawn(|| {
        for i in 1..4 {
            println!("spawned: {}", i);
            thread::sleep(Duration::from_millis(1));
        }
    });
    thread::sleep(Duration::from_millis(10));
}

Tworzenie wielu wątków

Można tworzyć kilka wątków w pętli i zbierać ich uchwyty w wektorze.

Następnie iteruje się po wektorze i wywołuje join dla każdego uchwytu, zapewniając zakończenie wszystkich wątków przed końcem programu.

use std::thread;

fn main() {
    let mut handles = vec![];
    for id in 0..3 {
        let h = thread::spawn(move || {
            println!("thread {}", id);
        });
        handles.push(h);
    }
    for h in handles {
        h.join().unwrap();
    }
}

Nazywanie wątków za pomocą Builder

Typ thread::Builder pozwala skonfigurować wątek przed jego utworzeniem. Można ustawić jego nazwę i rozmiar stosu.

Wątki z nazwami ułatwiają odczytywanie komunikatów o panice i debugowanie.

use std::thread;

fn main() {
    let h = thread::Builder::new()
        .name("worker".into())
        .spawn(|| {
            println!("running in named thread");
        })
        .unwrap();
    h.join().unwrap();
}

Paniki pozostają w wątku

Jeśli w utworzonym wątku wystąpi panika, domyślnie nie powoduje ona awarii całego programu. Panika pozostaje w tym wątku.

Gdy wywoła się join dla wątku, w którym wystąpiła panika, otrzymuje się wartość Err. Pozwala to wątkowi nadrzędnemu wykryć błąd.

use std::thread;

fn main() {
    let h = thread::spawn(|| {
        panic!("boom");
    });
    let result = h.join();
    println!("joined, is_err = {}", result.is_err());
}

Informacje o bieżącym wątku

Uruchomiony wątek można sprawdzić za pomocą thread::current. Zwraca ono uchwyt, którego metoda name podaje opcjonalną nazwę wątku.

Wątek główny również jest rzeczywistym wątkiem i zwykle nosi nazwę main.

use std::thread;

fn main() {
    let current = thread::current();
    println!("name: {:?}", current.name());
}

Zwracanie wartości z wątków

Domknięcie przekazane do spawn może zwracać wartość. Wartość ta pojawia się opakowana w Ok po wywołaniu join.

Jest to prosty sposób na wykonanie obliczeń w innym wątku i odczytanie wyniku później.

use std::thread;

fn main() {
    let h = thread::spawn(|| {
        let sum: i32 = (1..=10).sum();
        sum
    });
    let total = h.join().unwrap();
    println!("total = {}", total);
}

Szybkie sprawdzenie

Sprawdź, czy rozumiesz tworzenie wątków.

Podsumowanie

Nauczył(a) się Pan/Pani uruchamiać wątki za pomocą thread::spawn i domknięcia, które zwraca obiekt JoinHandle.

Wywołanie join oczekuje na zakończenie i udostępnia zwracaną wartość lub informację o panice. Dane wyjściowe z różnych wątków mogą przeplatać się w nieprzewidywalny sposób, a Builder pozwala nadawać wątkom nazwy.

W następnej części zobaczy Pan/Pani, jak przenosić dane do tworzonych wątków.

Często zadawane pytania

Czy lekcja „Uruchamianie wątków” jest bezpłatna?

Tak — pełny tekst „Uruchamianie 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 Learn Rust Coding, przejdź na CoddyKit PRO. Kurs Learn Rust Coding zawiera 4 lekcji w sumie.

Co nauczysz się w „Uruchamianie wątków”?

Uruchomi Pan/Pani kod współbieżnie. Ćwiczysz Learn Rust Coding 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ąć Learn Rust Coding?

Nie wymagamy żadnego doświadczenia. Learn Rust Coding 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 1 z 4.

Ile czasu zajmuje lekcja „Uruchamianie 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 Learn Rust Coding?

Tak. Każda lekcja Learn Rust Coding 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. Uruchamianie wątków
  2. Przenoszenie danych do wątków
  3. Współdzielenie za pomocą Arc i Mutex
  4. Dołączanie wątków i zbieranie wyników
← Powrót do Learn Rust Coding