Lær Rust-programmering · leksjon

Crossbeam-kanaler

Avanserte kanaler

Leksjon 4 av 413 trinn

Crossbeam-kanaler er en gratis leksjon i Lær Rust-programmering på CoddyKit. Dette er leksjon 4 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Lær Rust-programmering, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Lær Rust-programmering inneholder totalt 4 leksjoner.

Utover std mpsc

Standardkanalen mpsc har én mottaker: bare én receiver. Cratet crossbeam-channel tilbyr flere produsenter og flere mottakere (mpmc) med flere funksjoner og ofte bedre ytelse.

Høydepunkter:

  • Receiver-er som kan klones, ikke bare sendere.
  • En kraftig select!-makro for å vente på mange kanaler.
  • Begrensede, ubegrensede og spesielle kanaler, for eksempel ticks.

Legge til avhengigheten

Crossbeam er et eksternt crate, så legg det til i Cargo.toml:

[dependencies]
crossbeam-channel = "0.5"

Importer deretter funksjonene. Siden dette krever Cargo og et eksternt crate, viser kodeutdragene her API-et uten å kunne kjøres som frittstående kode.

// Cargo.toml
// [dependencies]
// crossbeam-channel = "0.5"

use crossbeam_channel::unbounded;

fn main() {
    let (s, r) = unbounded();
    s.send("hello").unwrap();
    println!("{}", r.recv().unwrap());
}

unbounded og bounded

Crossbeam tilbyr to hovedkonstruktører:

  • unbounded() vokser etter behov; send blokkerer aldri.
  • bounded(cap) har en buffer med fast størrelse; send blokkerer når den er full, noe som gir mottrykk.

En bounded(0)-kanal er en rendezvous-kanal der send og recv overfører data direkte.

use crossbeam_channel::bounded;
use std::thread;

fn main() {
    let (s, r) = bounded(2);
    thread::spawn(move || {
        for i in 1..=3 {
            s.send(i).unwrap();
        }
    });
    while let Ok(v) = r.recv() {
        println!("got {}", v);
    }
}

Flere mottakere

Den viktigste fordelen er at De kan klone Receiver. Flere arbeidstråder kan hente fra den samme kanalen, og hver melding går til nøyaktig én av dem. Dette er grunnlaget for en trådpool med arbeidstyveri.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (s, r) = unbounded();
    let mut workers = vec![];
    for id in 0..3 {
        let rx = r.clone();
        workers.push(thread::spawn(move || {
            while let Ok(job) = rx.recv() {
                println!("worker {} got job {}", id, job);
            }
        }));
    }
    for job in 0..6 { s.send(job).unwrap(); }
    drop(s);
    for w in workers { w.join().unwrap(); }
}

select!-makroen

select! lar én tråd vente på flere kanaloperasjoner og reagere på den som blir klar først. Den fungerer omtrent som en match over kanalhendelser og er ideell for å kombinere inndata fra flere kilder.

use crossbeam_channel::{unbounded, select};
use std::thread;

fn main() {
    let (s1, r1) = unbounded();
    let (s2, r2) = unbounded();
    thread::spawn(move || { s1.send("from one").unwrap(); });
    thread::spawn(move || { s2.send("from two").unwrap(); });
    for _ in 0..2 {
        select! {
            recv(r1) -> msg => println!("r1: {}", msg.unwrap()),
            recv(r2) -> msg => println!("r2: {}", msg.unwrap()),
        }
    }
}

Tidsavbrudd med select!

select! støtter en default-gren og en tidtakergren med recv(after(duration)), slik at De kan slutte å vente etter et tidsavbrudd i stedet for å blokkere for alltid. Dette er avgjørende for responsive systemer.

use crossbeam_channel::{unbounded, select, after};
use std::time::Duration;

fn main() {
    let (_s, r) = unbounded::<i32>();
    select! {
        recv(r) -> msg => println!("received {:?}", msg),
        recv(after(Duration::from_millis(100))) -> _ => {
            println!("timed out waiting for a message");
        }
    }
}

try_send og try_recv

I likhet med standardbiblioteket tilbyr crossbeam varianter som ikke blokkerer. try_send mislykkes umiddelbart hvis en begrenset kanal er full; try_recv mislykkes umiddelbart hvis ingen melding er klar. Begge returnerer en beskrivende feil som De kan bruke i en match.

use crossbeam_channel::{bounded, TrySendError};

fn main() {
    let (s, _r) = bounded(1);
    s.send(1).unwrap();
    match s.try_send(2) {
        Ok(()) => println!("sent"),
        Err(TrySendError::Full(v)) => println!("full, kept {}", v),
        Err(TrySendError::Disconnected(v)) => println!("closed, kept {}", v),
    }
}

tick og periodisk arbeid

Funksjonen tick(duration) returnerer en mottaker som leverer en melding med et fast intervall. Kombiner den med select! for å kjøre periodiske oppgaver sammen med andre kanaler, for eksempel et heartbeat eller en pollingløkke.

use crossbeam_channel::{tick, select};
use std::time::Duration;

fn main() {
    let ticker = tick(Duration::from_millis(50));
    let mut count = 0;
    while count < 3 {
        select! {
            recv(ticker) -> _ => {
                count += 1;
                println!("tick {}", count);
            }
        }
    }
}

En rørledning av trinn

Crossbeam utmerker seg når du bygger pipelines: trinn én produserer, trinn to transformerer, og trinn tre konsumerer. Hvert trinn kjører i sin egen tråd som er koblet sammen med kanaler, og klonede mottakere lar deg skalere ethvert trinn til flere arbeidere.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (in_s, in_r) = unbounded();
    let (out_s, out_r) = unbounded();
    thread::spawn(move || {
        for n in in_r { out_s.send(n * n).unwrap(); }
    });
    for n in 1..=4 { in_s.send(n).unwrap(); }
    drop(in_s);
    for sq in out_r { println!("square: {}", sq); }
}

Når Crossbeam er bedre enn std

Bruk crossbeam-channel når du trenger:

  • Flere konsumenter som deler én kø (arbeiderpooler).
  • select! over mange kanaler med tidsavbrudd.
  • Periodiske tidtakere via tick, integrert i utvalget.

For en enkel kanal med én produsent og én konsument fungerer standardbibliotekets mpsc fint, og den krever ingen avhengighet.

Kanaler lukkes når de forkastes

Akkurat som i std lukkes crossbeam-kanaler når alle senderne (på mottakersiden) eller alle mottakerne (på sendersiden) forkastes. Iterasjon over en mottaker avsluttes etter at den siste senderen forkastes. Bruk alltid drop, eller avgrens senderne til et scope, slik at arbeiderløkkene kan avsluttes på en ryddig måte.

use crossbeam_channel::unbounded;
use std::thread;

fn main() {
    let (s, r) = unbounded();
    let h = thread::spawn(move || {
        let total: i32 = r.iter().sum();
        println!("total: {}", total);
    });
    for i in 1..=5 { s.send(i).unwrap(); }
    drop(s); // closes channel so the loop ends
    h.join().unwrap();
}

Kort kontroll

Test forståelsen Deres av crossbeam-kanaler.

Oppsummering

De har utforsket crossbeam-kanaler:

  • De er mpmc: både sendere og mottakere kan klones.
  • unbounded() og bounded(n) styrer bufring og mottrykk.
  • select! venter på flere kanaler, med tidsavbrudd via after og periodisk tick.
  • try_send/try_recv er ikke-blokkerende.
  • Bruk crossbeam til arbeiderpooler og komplekse pipelines, og std mpsc til enkle kanaler.
Gratis å komme i gang

Lær deg Rust med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
39
Leksjoner
144

Ofte stilte spørsmål

Er leksjonen «Crossbeam-kanaler» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Lær Rust-programmering, inkludert «Crossbeam-kanaler», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Lær Rust-programmering inneholder totalt 4 leksjoner.

Hva lærer jeg i «Crossbeam-kanaler»?

Avanserte kanaler Du øver på Lær Rust-programmering med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Lær Rust-programmering?

Ingen tidligere erfaring er nødvendig. Lær Rust-programmering på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Crossbeam-kanaler»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Lær Rust-programmering-leksjonen?

Ja. Alle Lær Rust-programmering-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. mpsc-kanaler
  2. Dele tilstand med Arc/Mutex
  3. Avgrensede tråder
  4. Crossbeam-kanaler
← Tilbake til Lær Rust-programmering