githubdns icon indicating copy to clipboard operation
githubdns copied to clipboard

为什么在我本机跑是顺序执行的呢

Open LayneYy opened this issue 4 years ago • 11 comments

LayneYy avatar May 07 '20 17:05 LayneYy

你如何证明是顺序执行的?

nkbai avatar May 08 '20 01:05 nkbai

我是照着你写的思路写了一个,刚接触rust不久,可能有误解,麻烦大神帮我看看`use std::time::Duration;

use futures::future::join_all;

#[tokio::main] async fn main() { let mut v = Vec::new(); for _ in 1..10 { v.push(async move { println!("start {:?}", std::thread::current()); std::thread::sleep(Duration::from_millis(500)); }); }; join_all(v).await; } `

LayneYy avatar May 08 '20 01:05 LayneYy

我这个版本是每隔0.5秒打印一个,并且线程都是主线程,是哪个姿势不正确吗

LayneYy avatar May 08 '20 01:05 LayneYy

语法高亮一下,排版一下吧

nkbai avatar May 08 '20 01:05 nkbai

use std::time::Duration;

use futures::future::join_all;


#[tokio::main]
async fn main() {
    let mut v = Vec::new();
    for _ in 1..10 {
        v.push(async move {
            println!("start {:?}", std::thread::current());
            std::thread::sleep(Duration::from_millis(500));
        });
    };
    join_all(v).await;
}

LayneYy avatar May 08 '20 01:05 LayneYy

impl<F> Future for JoinAll<F>
where
    F: Future,
{
    type Output = Vec<F::Output>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut all_done = true;

        for mut elem in iter_pin_mut(self.elems.as_mut()) {
            if let Some(pending) = elem.as_mut().pending_pin_mut() {
                if let Poll::Ready(output) = pending.poll(cx) {
                    elem.set(ElemState::Done(Some(output)));
                } else {
                    all_done = false;
                }
            }
        }

        if all_done {
            let mut elems = mem::replace(&mut self.elems, Box::pin([]));
            let result = iter_pin_mut(elems.as_mut())
                .map(|e| e.take_done().unwrap())
                .collect();
            Poll::Ready(result)
        } else {
            Poll::Pending
        }
    }
}

/// Future for the [`join_all`] function.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct JoinAll<F>
where
    F: Future,
{
    elems: Pin<Box<[ElemState<F>]>>,
}

你期待什么样的输入,什么样的输出呢

nkbai avatar May 08 '20 02:05 nkbai

期待程序能够并发执行,几乎同时打印10行,然后停留0.5秒结束主线程

LayneYy avatar May 08 '20 02:05 LayneYy

那你别用std::thread::sleep啊,你用tokio提供的delay, 你把执行任务的线程阻塞了,他怎么执行其他task呢?

nkbai avatar May 08 '20 12:05 nkbai

tokio runtime 不会主动开多个线程吗

LayneYy avatar May 08 '20 13:05 LayneYy

https://stevenbai.top/rust/futures_explained_in_200_lines_of_rust/ 可以看一下我的这个博客,看看背后的机制是什么, 简单来说:

 if let Poll::Ready(output) = pending.poll(cx) {
                    elem.set(ElemState::Done(Some(output)));

这两行中的pending.poll,调用的就是你的

async move {
            println!("start {:?}", std::thread::current());
            std::thread::sleep(Duration::from_millis(500));
        }

这个async,sleep 500ms才会返回。

nkbai avatar May 08 '20 13:05 nkbai

好的,谢谢,那篇文章得有时间多看几遍才能整明白,昨天晚上尝试了一下,被第二个例子劝退了,哈哈

LayneYy avatar May 08 '20 13:05 LayneYy