Crossbeam-Kanäle
Erweiterte Kanäle
Crossbeam-Kanäle ist eine kostenlose Learn Rust Coding-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Learn Rust Coding-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.
Über std mpsc hinaus
Der standardmäßige mpsc-Channel ist Single-Consumer: Es gibt nur einen Receiver. Das Crate crossbeam-channel bietet Multi-Producer-Multi-Consumer-Channels (mpmc) mit mehr Funktionen und häufig besserer Leistung.
Wichtige Merkmale:
- Klonbare
Receiver, nicht nur Sender. - Ein leistungsfähiges
select!-Makro, das auf mehrere Channels wartet. - Begrenzte, unbegrenzte und spezielle Channels wie Taktgeber.
Die Abhängigkeit hinzufügen
Crossbeam ist ein externes Crate. Fügen Sie es daher zu Cargo.toml hinzu:
[dependencies]crossbeam-channel = "0.5"
Importieren Sie anschließend die Funktionen. Da hierfür Cargo und ein externes Crate benötigt werden, veranschaulichen die Snippets hier die API, anstatt eigenständig ausgeführt zu werden.
// 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 und bounded
Crossbeam bietet zwei wichtige Konstruktoren:
unbounded()wächst nach Bedarf;sendblockiert nie.bounded(cap)besitzt einen festen Puffer;sendblockiert, wenn dieser voll ist, und erzeugt dadurch Rückstau.
Ein bounded(0)-Channel ist ein Rendezvous-Channel, bei dem send und recv die Übergabe direkt ausführen.
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);
}
}Mehrere Consumer
Der entscheidende Vorteil: Sie können den Receiver klonen. Mehrere Worker-Threads können Nachrichten aus demselben Channel abrufen, wobei jede Nachricht genau bei einem von ihnen landet. Das ist die Grundlage eines Thread-Pools mit Work-Stealing.
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(); }
}Das select!-Makro
select! ermöglicht es einem Thread, auf mehrere Channel-Operationen zu warten und die zuerst bereite Operation auszuführen. Es ähnelt einem match über Channel-Ereignisse und eignet sich ideal, um Eingaben aus mehreren Quellen zu kombinieren.
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()),
}
}
}Timeouts mit select!
select! unterstützt einen default-Arm und einen Timer-Arm mit recv(after(duration)). Dadurch können Sie das Warten nach einem Timeout abbrechen, anstatt für immer zu blockieren. Das ist für reaktionsfähige Systeme unverzichtbar.
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 und try_recv
Wie die Standardbibliothek bietet auch Crossbeam nicht blockierende Varianten. try_send schlägt sofort fehl, wenn ein begrenzter Channel voll ist; try_recv schlägt sofort fehl, wenn keine Nachricht bereitsteht. Beide geben einen aussagekräftigen Fehler zurück, auf den Sie mit match reagieren können.
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 und periodische Arbeit
Die Funktion tick(duration) gibt einen Receiver zurück, der in einem festen Intervall eine Nachricht liefert. Kombinieren Sie sie mit select!, um periodische Aufgaben parallel zu anderen Channels auszuführen, etwa einen Heartbeat oder eine Polling-Schleife.
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);
}
}
}
}Eine Pipeline aus Stufen
Crossbeam eignet sich hervorragend zum Erstellen von Pipelines: Die erste Stufe erzeugt Daten, die zweite verarbeitet sie und die dritte konsumiert sie. Jede Stufe läuft in einem eigenen Thread, der über Channels verbunden ist, und geklonte Empfänger ermöglichen es, jede Stufe auf mehrere Worker zu skalieren.
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); }
}Wann Crossbeam std überlegen ist
Verwenden Sie crossbeam-channel, wenn Sie Folgendes benötigen:
- Mehrere Konsumenten, die sich eine Warteschlange teilen (Worker-Pools).
select!über mehrere Channels mit Timeouts.- Periodische Timer über
tick, integriert in die Auswahl.
Für eine einfache Pipe mit genau einem Produzenten und einem Konsumenten ist das standardmäßige mpsc ausreichend und benötigt keine zusätzliche Abhängigkeit.
Channels werden durch Verwerfen geschlossen
Wie bei std werden Crossbeam-Channels geschlossen, wenn alle Sender (auf der Empfängerseite) oder alle Empfänger (auf der Senderseite) verworfen wurden. Die Iteration über einen Empfänger endet, nachdem der letzte Sender verworfen wurde. Rufen Sie stets drop auf oder begrenzen Sie den Gültigkeitsbereich Ihrer Sender, damit Worker-Schleifen sauber beendet werden können.
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();
}Kurze Verständnisprüfung
Testen Sie Ihr Verständnis von Crossbeam-Channels.
Zusammenfassung
Sie haben Crossbeam-Channels kennengelernt:
- Sie sind mpmc: Sowohl Sender als auch Empfänger können geklont werden.
unbounded()undbounded(n)steuern Pufferung und Rückstaudruck.select!wartet auf mehrere Channels, mit Timeouts überafterund dem periodischentick.try_send/try_recvsind nicht blockierend.- Verwenden Sie Crossbeam für Worker-Pools und komplexe Pipelines und std mpsc für einfache Pipes.
Häufig gestellte Fragen
Ist die Lektion „Crossbeam-Kanäle“ kostenlos?
Ja — der vollständige Text von „Crossbeam-Kanäle“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Learn Rust Coding-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Learn Rust Coding-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Crossbeam-Kanäle“?
Erweiterte Kanäle Du übst Learn Rust Coding mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Learn Rust Coding zu starten?
Keine Vorkenntnisse erforderlich. Learn Rust Coding auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Crossbeam-Kanäle“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Learn Rust Coding-Lektion Code schreiben und ausführen?
Ja. Jede Learn Rust Coding-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- mpsc-Kanäle
- State mit Arc/Mutex teilen
- Bereichsbegrenzte Threads
- Crossbeam-Kanäle