如何并行运行多个调用 thread::sleep 的期货?

att*_*ona 5 future rust

我有一个缓慢的未来,在运行完成之前阻塞了 1 秒。

我尝试使用join组合器,但复合未来my_app按顺序执行期货:

#![feature(pin, futures_api, arbitrary_self_types)]

extern crate futures; // v0.3

use futures::prelude::*;
use futures::task::Context;
use std::pin::PinMut;
use std::{thread, time};
use futures::executor::ThreadPoolBuilder;

struct SlowComputation {}

impl Future for SlowComputation {
    type Output = ();

    fn poll(self: PinMut<Self>, _cx: &mut Context) -> Poll<Self::Output> {
        let millis = time::Duration::from_millis(1000);
        thread::sleep(millis);

        Poll::Ready(())
    }
}

fn main() {
    let fut1 = SlowComputation {};
    let fut2 = SlowComputation {};
    let my_app = fut1.join(fut2);

    ThreadPoolBuilder::new()
        .pool_size(5)
        .create()
        .expect("Failed to create threadpool")
        .run(my_app);
}
Run Code Online (Sandbox Code Playgroud)

为什么这样join工作?我预计期货会在不同的线程上产生。

实现目标的正确方法是什么?

货物.toml:

[dependencies]
futures-preview = "0.3.0-alfa.6"
Run Code Online (Sandbox Code Playgroud)

结果:

#![feature(pin, futures_api, arbitrary_self_types)]

extern crate futures; // v0.3

use futures::prelude::*;
use futures::task::Context;
use std::pin::PinMut;
use std::{thread, time};
use futures::executor::ThreadPoolBuilder;

struct SlowComputation {}

impl Future for SlowComputation {
    type Output = ();

    fn poll(self: PinMut<Self>, _cx: &mut Context) -> Poll<Self::Output> {
        let millis = time::Duration::from_millis(1000);
        thread::sleep(millis);

        Poll::Ready(())
    }
}

fn main() {
    let fut1 = SlowComputation {};
    let fut2 = SlowComputation {};
    let my_app = fut1.join(fut2);

    ThreadPoolBuilder::new()
        .pool_size(5)
        .create()
        .expect("Failed to create threadpool")
        .run(my_app);
}
Run Code Online (Sandbox Code Playgroud)

mol*_*olf 6

如果将 futures 与join()它们结合起来,它们将被转换为单个任务,在单个线程上运行。

如果期货表现良好,它们将以事件驱动(异步)方式并行运行。您希望您的应用程序休眠 1 秒钟。

但不幸的是,你实现的未来表现并不好。它会阻塞当前线程一秒钟,在此期间不允许进行任何其他工作。由于期货在同一线程上运行,因此它们不能同时运行。您的应用程序将休眠 2 秒钟。

请注意,如果您将示例更改为以下内容,期货将保持独立的任务,您可以在线程池上并行运行它们:

fn main() {
    let fut1 = SlowComputation {};
    let fut2 = SlowComputation {};

    let mut pool = ThreadPoolBuilder::new()
        .pool_size(5)
        .create()
        .expect("Failed to create threadpool");

    pool.spawn(fut1);
    pool.run(fut2);
}
Run Code Online (Sandbox Code Playgroud)

非常不鼓励编写阻塞主线程的期货,在实际应用程序中,您可能应该使用库提供的计时器,例如tokio::timer::Delaytokio::timer::timeout::Timeout