有很多方法可以在线程之间发送数据,但没有明确的“最佳”解决方案。这取决于您的情况。
仅使用thread::join
许多人不知道只使用thread
API 就可以非常容易地发送数据,但只能发送两次:一次发送到新线程,一次发送回来。
use std::thread;
let data_in = String::from("lots of data");
let handle = thread::spawn(move || {
println!("{}", data_in);
let data_out = heavy_compuations();
data_out
});
let data_out = handle.join().expect("thread panicked :(");
println!("{}", data_out);
(Playground)
对于只被用来完成某一个特定任务的线程,这非常有用。请注意,在闭包之前加上 move
关键字,以确保所有引用的变量都被移入了闭包(随后就会被移至另一线程)。
std
中的通道
标准库中提供了一个 multi producer single consumer 通道,位于 std::sync::mpsc
中。 你可以通过通道发送任意数量的值,因此它可以在更多情况下使用。以下是一个简单的示例:
use std::{
sync::mpsc::channel,
thread,
time::Duration,
};
let (sender, receiver) = channel();
thread::spawn(move || {
sender.send("heavy computation 1").expect("receiver hung up :(");
thread::sleep(Duration::from_millis(500));
sender.send("heavy computation 2").expect("receiver hung up :(");
});
let result1 = receiver.recv().unwrap();
let result2 = receiver.recv().unwrap();
(Playground)
当然,您可以创建另一个频道以提供双向通信。
crossbeam
的更强大的通道
不幸的是,标准库目前仅提供了限于单个消费者(即Receiver
无法克隆)的通道。要获得更强大的通道,您可能需要使用来自优秀的crossbeam
库中的通道。它们的描述:
此crate是带有更多功能和更好性能的std::sync::mpsc
替代品。
特别地,它是mpmc(多个消费者!)通道。这提供了一种轻松地在多个线程之间共享工作的方式。例如:
use std::thread;
let (sender, receiver) = crossbeam_channel::unbounded();
for _ in 0..num_cpus::get() {
let receiver = receiver.clone();
thread::spawn(move || {
for job in receiver {
}
});
}
for x in 0..10_000 {
sender.send(x).expect("all threads hung up :(");
}
(游乐场)
再次,添加另一个通道允许您将结果发送回主线程。
其他方法
有很多其他的箱子可以提供在线程之间发送数据的其他方式。太多了,无法在此列出。
请注意,通过Mutex
、原子、无锁数据结构和许多其他方式进行数据的 发送 不是在线程之间通信的唯一方式。共享 数据也是一种可能性。这在概念上非常不同。根据情况,发送或共享数据是描述跨线程通信的更好方式。