【发布时间】:2018-09-25 12:41:33
【问题描述】:
给定几个以Output 值完成的线程,我如何获得第一个产生的Output?理想情况下,仍然能够在稍后按照它们的生成顺序获取剩余的Outputs,并记住某些线程可能会或可能不会终止。
例子:
struct Output(i32);
fn main() {
let mut spawned_threads = Vec::new();
for i in 0..10 {
let join_handle: ::std::thread::JoinHandle<Output> = ::std::thread::spawn(move || {
// pretend to do some work that takes some amount of time
::std::thread::sleep(::std::time::Duration::from_millis(
(1000 - (100 * i)) as u64,
));
Output(i) // then pretend to return the `Output` of that work
});
spawned_threads.push(join_handle);
}
// I can do this to wait for each thread to finish and collect all `Output`s
let outputs_in_order_of_thread_spawning = spawned_threads
.into_iter()
.map(::std::thread::JoinHandle::join)
.collect::<Vec<::std::thread::Result<Output>>>();
// but how would I get the `Output`s in order of completed threads?
}
我可以使用共享队列/通道/类似的方法自己解决问题,但是是否有内置 API 或现有库可以更优雅地为我解决这个用例?
我正在寻找这样的 API:
fn race_threads<A: Send>(
threads: Vec<::std::thread::JoinHandle<A>>
) -> (::std::thread::Result<A>, Vec<::std::thread::JoinHandle<A>>) {
unimplemented!("so far this doesn't seem to exist")
}
(Rayon's join 是我能找到的最接近的,但是 a)它只运行 2 个闭包而不是任意数量的闭包,并且 b)线程池 w/ 工作窃取方法不会对我的用例来说,有一些可能会永远运行的闭包。)
可以使用来自 How to check if a thread has finished in Rust? 的指针来解决这个用例,就像可以使用 MPSC 通道来解决这个用例一样,但是在这里我需要一个干净的 API 来竞争 n 线程(或失败) , n n 线程上的闭包)。
【问题讨论】:
-
你可以只通过 mpsc 发送者到达线程并在接收端只消耗一个结果。
-
我相信How to check if a thread has finished in Rust?已经回答了您的问题。如果您不同意,请edit您的问题解释这些答案如何没有回答这个问题。
-
@the8472 是的,这就是我所说的“使用共享队列/通道/类似”的意思——我正在寻求一种比这更简洁的方法。
-
@Shepmaster 我已经编辑了这个问题,以澄清我正在寻求现有的收集结果的解决方案;我认为使用您链接的 Q,我仍然需要自己滚动“在队列中收集结果”(尽管感谢您的指针!)。
-
关于惯用 Rust 的旁注:你真的应该导入一些类型。拥有这么多完全合格的东西真是丑陋。
标签: multithreading concurrency rust