我希望使用Rust创建一个简单的调度程序,以便在定义的时间运行多个并发函数,但如果它们还没有完成,则不要启动更多函数。
例如,如果定义的间隔为一秒钟,调度程序应该运行这些函数,并且如果之前的函数还没有返回,则不要启动更多函数。目标是防止多次运行同一函数。
我用Go创建了一个工作示例,方法如下:
我对这种方法的问题在于任务不等待前一个函数被调用,因此函数会重新开始运行,即使之前它们已经在运行了,我在这里缺少像Go的
是否可能只使用标准库就能实现这一点?这主要是为了学习目的,可能有一种非常简单的方法来做到这一点,我可以避免额外的复杂性。
最终,我想通过HTTP定期监视一些网站(只获取返回的状态码),但在获得所有响应之前不查询它们全部。
例如,如果定义的间隔为一秒钟,调度程序应该运行这些函数,并且如果之前的函数还没有返回,则不要启动更多函数。目标是防止多次运行同一函数。
我用Go创建了一个工作示例,方法如下:
package main
import (
"fmt"
"sync"
"time"
)
func myFunc(wg *sync.WaitGroup) {
fmt.Printf("now: %+s\n", time.Now())
time.Sleep(3 * time.Second)
wg.Done()
}
func main() {
quit := make(chan bool)
t := time.NewTicker(time.Second)
go func() {
for {
select {
case <-t.C:
var wg sync.WaitGroup
for i := 0; i <= 4; i++ {
wg.Add(1)
go myFunc(&wg)
}
wg.Wait()
fmt.Printf("--- done ---\n\n")
case <-quit:
return
}
}
}()
<-time.After(time.Minute)
close(quit)
}
由于在Rust标准库中没有像Go的NewTicker
这样的东西,我使用了Tokio并且想出了这个方法
extern crate futures;
extern crate tokio;
use futures::future::lazy;
use std::{thread, time};
use tokio::prelude::*;
use tokio::timer::Interval;
fn main() {
let task = Interval::new(time::Instant::now(), time::Duration::new(1, 0))
.for_each(|interval| {
println!("Interval: {:?}", interval);
for i in 0..5 {
tokio::spawn(lazy(move || {
println!("I am i: {}", i);
thread::sleep(time::Duration::from_secs(3));
Ok(())
}));
}
Ok(())
})
.map_err(|e| panic!("interval errored; err={:?}", e));
tokio::run(task);
}
我对这种方法的问题在于任务不等待前一个函数被调用,因此函数会重新开始运行,即使之前它们已经在运行了,我在这里缺少像Go的
sync.WaitGroup
这样的东西。有什么可以用来实现与工作示例相同的结果吗?是否可能只使用标准库就能实现这一点?这主要是为了学习目的,可能有一种非常简单的方法来做到这一点,我可以避免额外的复杂性。
最终,我想通过HTTP定期监视一些网站(只获取返回的状态码),但在获得所有响应之前不查询它们全部。
thread::sleep
:为什么Future::select会首先选择休眠时间更长的future? - Shepmaster