multithreading - 在线程之间发送数据的惯用方式是什么?
问题描述
我想在一个单独的线程中做一些计算,然后从主线程中恢复数据。在 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!
(游乐场)
这对于刚刚为执行一项特定工作而生成的线程非常有用。注意move
闭包之前的关键字,它确保所有引用的变量都被移动到闭包中(然后被移动到另一个线程)。
来自的频道std
标准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();
(游乐场)
当然,您也可以创建另一个渠道来提供另一个方向的通信。
更强大的渠道crossbeam
不幸的是,标准库目前只提供仅限于单个消费者的渠道(即Receiver
不能被克隆)。要获得更强大的频道,您可能想要使用来自 awesome crossbeam
library的频道。他们的描述:
std::sync::mpsc
此板条箱是具有更多功能和更好性能的替代品。
特别是,它是一个mpmc(多消费者!)频道。这提供了一种在多个线程之间轻松共享工作的好方法。例子:
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 :(");
}
(游乐场)
同样,添加另一个通道允许您将结果传达回主线程。
其他方法
还有很多其他 crate 提供了在线程之间发送数据的其他方式。太多了,这里就不一一列举了。
请注意,发送数据并不是线程间通信的唯一方式。也有可能通过、原子、无锁数据结构和许多其他方式在线程之间共享数据。这在概念上是非常不同的。发送或共享数据是否是描述跨线程通信的更好方式取决于具体情况。Mutex
推荐阅读
- javascript - Chart JS 无动画折线图
- rabbitmq - RabbitMQ 是否可以在 RabbitMQ 中复制一些消息?
- java - Java Webservice:GET 返回了 401 Unauthorized 的响应状态
- python - 将数字范围添加到列表中的每个元素
- apache - 将所有请求重定向到 Index.html
- node.js - openstack、pkgcloud 和节点 js
- database - 无法从 Oracle RAW 数据中解码所有信息
- machine-learning - 如何从此热图中选择变量?
- html - CSS 从左到右滑动面板
- javascript - Href 链接未正确呈现