将一堆任务转换成在线程池上执行的期货的Rust习语是什么?



在java中,我会使用ExecutorService,这是一个固定大小的线程池和submit(Callable),然后get()的结果。

在Rust中与之匹配的习语是什么?我可以thread::spawn()一堆任务并join()它们,但是它将为每个任务创建一个线程,并且我想限制并发线程的数量。

为了使事情更具体一点,这里是一些代码的粗略草图:

let a4 = thread_pool.spawn(|| svg.compute_stitches("path674"));
let a1 = thread_pool.spawn(|| svg.compute_stitches("path653"));
let a2 = thread_pool.spawn(|| svg.compute_stitches("g659"));
let a3 = thread_pool.spawn(|| svg.compute_stitches("path664"));
let a5 = thread_pool.spawn(|| svg.compute_stitches("path679"));
stitcher.stitch(a1.join());
stitcher.stitch(a2.join());
stitcher.next_color();
stitcher.stitch(a3.join());
stitcher.next_color();
stitcher.stitch(a4.join());
stitcher.next_color();
stitcher.stitch(a5.join());

目前我已经推出了自己的解决方案。它看起来像这样:

use std::sync::mpsc;
use std::sync::mpsc::{Receiver, RecvError};
use std::{panic, thread};
pub struct ThreadPool {
channel: spmc::Sender<Mission>,
}
impl ThreadPool {
pub fn new(thread_count: usize) -> ThreadPool {
let (tx, rx) = spmc::channel();
for _ in 0..thread_count {
let rx2 = rx.clone();
thread::spawn(move || Self::work_loop(rx2));
}
ThreadPool { channel: tx }
}
pub fn spawn<F, T: 'static>(&mut self, task: F) -> Answer<T>
where
F: FnOnce() -> T + std::panic::UnwindSafe + Send + 'static,
{
let (tx, rx) = mpsc::channel();
let mission = Mission {
go: Box::new(move || {
let tmp = panic::catch_unwind(task);
tx.send(tmp).unwrap()
}),
};
self.channel.send(mission).unwrap();
Answer { channel: rx }
}
fn work_loop(channel: spmc::Receiver<Mission>) {
while let Ok(mission) = channel.recv() {
(mission.go)();
}
}
}
struct Mission {
go: Box<dyn FnOnce()>,
}
unsafe impl Send for Mission {}
pub struct Answer<T> {
channel: Receiver<std::thread::Result<T>>,
}
impl<T> Answer<T> {
pub fn get(self) -> Result<T, RecvError> {
let tmp = self.channel.recv();
match tmp {
Ok(rval) => match rval {
Ok(rval) => Ok(rval),
Err(explosion) => panic::resume_unwind(explosion),
},
Err(e) => Err(e),
}
}
}

最新更新