我想在单独的线程中进行一些计算,然后从主线程中恢复数据。在 Rust 中将一些数据从一个线程传递到另一个线程的规范方法是什么?
fn main() {
let handle = std::thread::spawn(|| {
// I want to send this to the main thread:
String::from("Hello world!")
});
// How to recover the data from the other thread?
handle.join().unwrap();
}
最佳答案
有很多方法可以在线程之间发送数据——没有一个明确的“最佳”解决方案。这取决于你的情况。
仅使用 thread::join
很多人没有意识到,您只需使用 thread
就可以非常轻松地发送数据。 API,但只有两次:一次到新线程,一次返回。
use std::thread;
let data_in = String::from("lots of data");
let handle = thread::spawn(move || {
println!("{}", data_in); // we can use the data here!
let data_out = heavy_compuations();
data_out // <-- simply return the data from the closure
});
let data_out = handle.join().expect("thread panicked :(");
println!("{}", data_out); // we can use the data generated in the thread here!
( Playground )
这对于刚刚产生以完成一项特定工作的线程非常有用。请注意
move
闭包之前的关键字,确保所有引用的变量都移动到闭包中(然后移动到另一个线程)。来自
std
的 channel 标准库提供了 multi producer single consumer channel in
std::sync::mpsc
.您可以通过一个 channel 发送任意多个值,因此可以在更多情况下使用。简单的例子: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 )
当然,您也可以创建另一个 channel 来提供另一个方向的通信。
更强大的 channel 来自
crossbeam
不幸的是,标准库目前仅提供仅限于单个使用者的 channel (即
Receiver
无法克隆)。要获得更强大的 channel ,您可能需要使用 channels from the awesome crossbeam
library .他们的描述:This crate is an alternative to
std::sync::mpsc
with more features and better performance.
特别是,它是一个 mpmc(多消费者!) channel 。这提供了一种在多个线程之间轻松共享工作的好方法。例子:
use std::thread;
// You might want to use a bounded channel instead...
let (sender, receiver) = crossbeam_channel::unbounded();
for _ in 0..num_cpus::get() {
let receiver = receiver.clone(); // clone for this thread
thread::spawn(move || {
for job in receiver {
// process job
}
});
}
// Generate jobs
for x in 0..10_000 {
sender.send(x).expect("all threads hung up :(");
}
( Playground )
同样,添加另一个 channel 允许您将结果传送回主线程。
其他方法
还有很多其他的 crate 提供了在线程之间发送数据的其他方法。太多了,无法在此一一列出。
请注意,发送数据并不是线程间通信的唯一方式。还可以通过
Mutex
在线程之间共享数据, atomics 、无锁数据结构等多种方式。这在概念上是非常不同的。这取决于具体情况,发送或共享数据是描述跨线程通信的更好方式。
关于multithreading - 在线程之间发送数据的惯用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59075477/