我希望能够创建 n 个线程,并且这些线程之间可以以环形拓扑结构进行通讯,例如,线程 0 可以向线程 1 发送消息,线程 1 可以向线程 2 发送消息,以此类推,而线程 n 可以向线程 0 发送消息。
以下是当 n=3 时我想要实现的示例:
以下是当 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();
我在循环中创建通道,将它们存储在向量中,重新排序发送方,并将其存储在新向量中,然后为每个发送者和接收者(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();
}
这种方法行不通,因为无法复制 Sender 以创建一个新的向量。 但是,如果我使用引用(& 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();
我无法启动线程,因为std::sync::mpsc::Sender<i32>
不能在线程之间安全地共享。
collect
构建children
。 - user4815162342rotate_right
更改为rotate_left
可以解决这个问题。(另外,我认为你在编辑时忘记省略 child 变量了) - jhscheer