rust学习-tokio::time

示例

rust 复制代码
use std::time::Duration;
use tokio::{task, time::interval};

#[tokio::main]
async fn main() {
    let mut interval = interval(Duration::from_secs(1));
    let handle = task::spawn(async move {
        loop {
            interval.tick().await;
            println!("tick");
        }
    });

    handle.await.unwrap();
}

interval和sleep的区别

tick周期大于异步任务周期

rust 复制代码
use tokio::time;
use chrono::{DateTime, Local};

async fn task_that_takes_a_second() {
    let now: DateTime<Local> = Local::now();
    println!("Current task time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    time::sleep(time::Duration::from_secs(2)).await;
    let now: DateTime<Local> = Local::now();
    println!("Current task time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
}

#[tokio::main]
async fn main() {
    let mut interval = time::interval(time::Duration::from_secs(3));
    for _i in 0..5 {
        let now: DateTime<Local> = Local::now();
        println!("Current main time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
        interval.tick().await;
        let now: DateTime<Local> = Local::now();
        println!("Current main time mid is: {}", now.format("%Y-%m-%d %H:%M:%S"));
        task_that_takes_a_second().await;
        let now: DateTime<Local> = Local::now();
        println!("Current main time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    }
}
rust 复制代码
Current main time before is: 2023-08-11 13:46:48
Current main time mid is: 2023-08-11 13:46:48 // 第一次,立即触发
Current task time before is: 2023-08-11 13:46:48
Current task time after is: 2023-08-11 13:46:50
Current main time after is: 2023-08-11 13:46:50

Current main time before is: 2023-08-11 13:46:50
Current main time mid is: 2023-08-11 13:46:51 // 距离上一次3秒
Current task time before is: 2023-08-11 13:46:51
Current task time after is: 2023-08-11 13:46:53
Current main time after is: 2023-08-11 13:46:53

Current main time before is: 2023-08-11 13:46:53
Current main time mid is: 2023-08-11 13:46:54 // 距离上一次3秒
Current task time before is: 2023-08-11 13:46:54
Current task time after is: 2023-08-11 13:46:56
Current main time after is: 2023-08-11 13:46:56

Current main time before is: 2023-08-11 13:46:56
Current main time mid is: 2023-08-11 13:46:57  // 距离上一次3秒
Current task time before is: 2023-08-11 13:46:57
Current task time after is: 2023-08-11 13:46:59
Current main time after is: 2023-08-11 13:46:59

Current main time before is: 2023-08-11 13:46:59
Current main time mid is: 2023-08-11 13:47:00 // 距离上一次3秒
Current task time before is: 2023-08-11 13:47:00
Current task time after is: 2023-08-11 13:47:02
Current main time after is: 2023-08-11 13:47:02

tick周期小于异步任务周期

rust 复制代码
use tokio::time;
use chrono::{DateTime, Local};

async fn task_that_takes_a_second() {
    let now: DateTime<Local> = Local::now();
    println!("Current task time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    time::sleep(time::Duration::from_secs(5)).await;
    let now: DateTime<Local> = Local::now();
    println!("Current task time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
}

#[tokio::main]
async fn main() {
    let mut interval = time::interval(time::Duration::from_secs(3));
    for _i in 0..5 {
        let now: DateTime<Local> = Local::now();
        println!("Current main time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
        interval.tick().await;
        let now: DateTime<Local> = Local::now();
        println!("Current main time mid is: {}", now.format("%Y-%m-%d %H:%M:%S"));
        task_that_takes_a_second().await;
        let now: DateTime<Local> = Local::now();
        println!("Current main time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    }
}
rust 复制代码
Current main time before is: 2023-08-11 13:51:24
Current main time mid is: 2023-08-11 13:51:24
Current task time before is: 2023-08-11 13:51:24
Current task time after is: 2023-08-11 13:51:29
Current main time after is: 2023-08-11 13:51:29

Current main time before is: 2023-08-11 13:51:29
Current main time mid is: 2023-08-11 13:51:29 // 举例上一次超过3秒
Current task time before is: 2023-08-11 13:51:29
Current task time after is: 2023-08-11 13:51:34
Current main time after is: 2023-08-11 13:51:34

Current main time before is: 2023-08-11 13:51:34
Current main time mid is: 2023-08-11 13:51:34  // 举例上一次超过3秒
Current task time before is: 2023-08-11 13:51:34
Current task time after is: 2023-08-11 13:51:39
Current main time after is: 2023-08-11 13:51:39

Current main time before is: 2023-08-11 13:51:39
Current main time mid is: 2023-08-11 13:51:39  // 举例上一次超过3秒
Current task time before is: 2023-08-11 13:51:39
Current task time after is: 2023-08-11 13:51:44
Current main time after is: 2023-08-11 13:51:44

Current main time before is: 2023-08-11 13:51:44
Current main time mid is: 2023-08-11 13:51:44  // 举例上一次超过3秒
Current task time before is: 2023-08-11 13:51:44
Current task time after is: 2023-08-11 13:51:49
Current main time after is: 2023-08-11 13:51:49

timeout

rust 复制代码
use tokio::time::{timeout, Duration};
use tokio::time;
use chrono::{DateTime, Local};

async fn long_future() {
    let now: DateTime<Local> = Local::now();
    println!("Current task time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    time::sleep(time::Duration::from_secs(5)).await;
    let now: DateTime<Local> = Local::now();
    println!("Current task time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
}

#[tokio::main]
async fn main() {
    for _i in 0..5 {
        let now: DateTime<Local> = Local::now();
        println!("Current main time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    
        let res = timeout(Duration::from_secs(1), long_future()).await;
    
        let now: DateTime<Local> = Local::now();
        println!("Current main time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
        
        if res.is_err() {
                println!("operation timed out");
        }
    }
}

interval_at

rust 复制代码
pub fn interval_at(start: Instant, period: Duration) -> Interval
rust 复制代码
use tokio::time::{interval_at, Duration, Instant};
use chrono::{DateTime, Local};

#[tokio::main]
async fn main() {
    let start = Instant::now() + Duration::from_secs(5);
    let mut interval = interval_at(start, Duration::from_secs(3)); // 不会立即开始

    let now: DateTime<Local> = Local::now();
    println!("Current task time now is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    interval.tick().await; // ticks after 3s
    let now: DateTime<Local> = Local::now();
    println!("Current task time now is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    interval.tick().await; // ticks after 3s
    let now: DateTime<Local> = Local::now();
    println!("Current task time now is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    interval.tick().await; // ticks after 3s
    let now: DateTime<Local> = Local::now();
    println!("Current task time now is: {}", now.format("%Y-%m-%d %H:%M:%S"));
}
rust 复制代码
Current task time now is: 2023-08-11 19:34:30
Current task time now is: 2023-08-11 19:34:35
Current task time now is: 2023-08-11 19:34:38
Current task time now is: 2023-08-11 19:34:41

MissedTickBehavior

rust 复制代码
use tokio::time;
use chrono::{DateTime, Local};
use tokio::time::MissedTickBehavior;

async fn task_that_takes_a_second() {
    let now: DateTime<Local> = Local::now();
    println!("Current task time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    time::sleep(time::Duration::from_secs(5)).await;
    let now: DateTime<Local> = Local::now();
    println!("Current task time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
}

#[tokio::main]
async fn main() {
    let mut interval = time::interval(time::Duration::from_secs(3));
    interval.set_missed_tick_behavior(MissedTickBehavior::Delay);

        for _i in 0..5 {
            let now: DateTime<Local> = Local::now();
            println!("Current main time before is: {}", now.format("%Y-%m-%d %H:%M:%S"));
            interval.tick().await;
            let now: DateTime<Local> = Local::now();
            println!("Current main time mid is: {}", now.format("%Y-%m-%d %H:%M:%S"));
            task_that_takes_a_second().await;
            let now: DateTime<Local> = Local::now();
            println!("Current main time after is: {}", now.format("%Y-%m-%d %H:%M:%S"));
    }
}

在 Rust 的 tokio 库中,MissedTickBehavior 是一个枚举类型,表示当 Interval 频率计时器在某个周期中错过某个间隔时如何处理。具体来说,它有以下三个变体:

  • Burst:表示如果错过计时间隔,则会立即执行多个周期,直到被重新赶上。
  • Delay:表示如果错过计时间隔,则在下一个可用的计时间隔时执行周期。
  • Skip:表示如果错过计时间隔,则跳过它并继续执行下一个计时间隔的周期。
    一般情况下, Burst 和 Delay 会导致执行速率加速,Skip 会导致执行速率降低但保证数据与频率同步。
rust 复制代码
#[tokio::main]
async fn main() {
    let mut interval_burst = time::interval(Duration::from_millis(5));
    interval_burst.set_missed_tick_behavior(time::MissedTickBehavior::Burst);

    let mut interval_delay = time::interval(Duration::from_millis(5));
    interval_delay.set_missed_tick_behavior(time::MissedTickBehavior::Delay);

    let mut count_burst = 0;
    let mut count_delay = 0;

    // 运行到20000次以上才会看出差异
    loop {
        select! {
            _ = interval_burst.tick() => {
                count_burst += 1;
                println!("Burst: tick #{}", count_burst);
            }
            _ = interval_delay.tick() => {
                count_delay += 1;
                println!("Delay: tick #{}", count_delay);
            }
        }
    }
}
相关推荐
niandb35 分钟前
The Rust Programming Language 学习 (九)
windows·rust
zhuyixiangyyds3 小时前
day21和day22学习Pandas库
笔记·学习·pandas
每次的天空3 小时前
Android学习总结之算法篇四(字符串)
android·学习·算法
背影疾风4 小时前
C++学习之路:指针基础
c++·学习
苏克贝塔5 小时前
CMake学习--Window下VSCode 中 CMake C++ 代码调试操作方法
c++·vscode·学习
odoo中国6 小时前
深度学习 Deep Learning 第15章 表示学习
人工智能·深度学习·学习·表示学习
电星托马斯6 小时前
C++中顺序容器vector、list和deque的使用方法
linux·c语言·c++·windows·笔记·学习·程序人生
清晨朝暮6 小时前
【算法学习计划】贪心算法(下)
学习
Source.Liu6 小时前
【学Rust写CAD】26 图形像素获取(pixel_fetch.rs)
rust·cad
zhu12893035566 小时前
用Rust和WebAssembly打造轻量级前端加密工具
前端·rust·wasm