jhs*_*eer 3 multithreading channel rust
我想产生 n 个能够与环形拓扑中的其他线程通信的线程,例如线程 0 可以将消息发送到线程 1,线程 1 到线程 2,等等,线程 n 到线程 0。
这是我想用 n=3 实现的一个例子:
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
let (tx0, rx0): (Sender<i32>, Receiver<i32>) = mpsc::channel();
let (tx1, rx1): (Sender<i32>, Receiver<i32>) = mpsc::channel();
let (tx2, rx2): (Sender<i32>, Receiver<i32>) = mpsc::channel();
let child0 = thread::spawn(move || {
tx0.send(0).unwrap();
println!("thread 0 sent: 0");
println!("thread 0 recv: {:?}", rx2.recv().unwrap());
});
let child1 = thread::spawn(move || {
tx1.send(1).unwrap();
println!("thread 1 sent: 1");
println!("thread 1 recv: {:?}", rx0.recv().unwrap());
});
let child2 = thread::spawn(move || {
tx2.send(2).unwrap();
println!("thread 2 sent: 2");
println!("thread 2 recv: {:?}", rx1.recv().unwrap());
});
child0.join();
child1.join();
child2.join();
Run Code Online (Sandbox Code Playgroud)
在这里,我在循环中创建通道,将它们存储在一个向量中,重新排序发送方,将它们存储在一个新的向量中,然后生成每个线程,每个线程都有自己的发送方-接收方(tx1/rx0、tx2/rx1 等)对。
const NTHREADS: usize = 8;
// create n channels
let channels: Vec<(Sender<i32>, Receiver<i32>)> =
(0..NTHREADS).into_iter().map(|_| mpsc::channel()).collect();
// switch tupel entries for the senders to create ring topology
let mut channels_ring: Vec<(Sender<i32>, Receiver<i32>)> = (0..NTHREADS)
.into_iter()
.map(|i| {
(
channels[if i < channels.len() - 1 { i + 1 } else { 0 }].0,
channels[i].1,
)
})
.collect();
let mut children = Vec::new();
for i in 0..NTHREADS {
let (tx, rx) = channels_ring.remove(i);
let child = thread::spawn(move || {
tx.send(i).unwrap();
println!("thread {} sent: {}", i, i);
println!("thread {} recv: {:?}", i, rx.recv().unwrap());
});
children.push(child);
}
for child in children {
let _ = child.join();
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为无法复制 Sender 以创建新矢量。但是,如果我使用 refs ( & Sender):
let mut channels_ring: Vec<(&Sender<i32>, Receiver<i32>)> = (0..NTHREADS)
.into_iter()
.map(|i| {
(
&channels[if i < channels.len() - 1 { i + 1 } else { 0 }].0,
channels[i].1,
)
})
.collect();
Run Code Online (Sandbox Code Playgroud)
我无法生成线程,因为std::sync::mpsc::Sender<i32>不能在线程之间安全地共享。
Senders 和Receivers 不能共享,因此您需要将它们移动到各自的线程中。这意味着在迭代它时将它们从Vec或 否则消耗掉Vec- 不允许向量处于无效状态(有孔),即使作为中间步骤也是如此。迭代向量into_iter将通过使用它们来实现这一点。
你可以用来让发送者和接收者在一个循环中配对的一个小技巧是创建两个向量;一位发送者和一位接收者;然后旋转一个,以便每个向量中的相同索引将为您提供所需的对。
use std::sync::mpsc::{self, Receiver, Sender};
use std::thread;
fn main() {
const NTHREADS: usize = 8;
// create n channels
let (mut senders, receivers): (Vec<Sender<i32>>, Vec<Receiver<i32>>) =
(0..NTHREADS).into_iter().map(|_| mpsc::channel()).unzip();
// move the first sender to the back
senders.rotate_left(1);
let children: Vec<_> = senders
.into_iter()
.zip(receivers.into_iter())
.enumerate()
.map(|(i, (tx, rx))| {
thread::spawn(move || {
tx.send(i as i32).unwrap();
println!("thread {} sent: {}", i, i);
println!("thread {} recv: {:?}", i, rx.recv().unwrap());
})
})
.collect();
for child in children {
let _ = child.join();
}
}
Run Code Online (Sandbox Code Playgroud)