A channel moves ownership between threads. mpsc is multi-producer, single-consumer: clone the sender as many times as you need, keep one receiver.
let (tx, rx) = mpsc::channel::<u64>();
for id in 0..3 {
let tx = tx.clone();
thread::spawn(move || { tx.send(id).unwrap(); });
}
drop(tx); // drop the original, or rx never ends
for value in rx { ... }
That drop(tx) is the detail people miss. The receiver's iterator ends when every sender is gone — and the original tx in main is one of them.
