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);
            }
        }
    }
}
相关推荐
charlie1145141913 小时前
从0开始使用面对对象C语言搭建一个基于OLED的图形显示框架(协议层封装)
c语言·驱动开发·单片机·学习·教程·oled
马船长4 小时前
[BSidesCF 2020]Had a bad day1
学习
黄交大彭于晏4 小时前
三端回链增加截图功能
学习
linwq85 小时前
设计模式学习(二)
java·学习·设计模式
Fhd-学习笔记5 小时前
《大语言模型》综述学习笔记
笔记·学习·语言模型
美味小鱼5 小时前
实践Rust:编写一个猜数字游戏
开发语言·游戏·rust
简知圈7 小时前
【04-自己画P封装,并添加已有3D封装】
笔记·stm32·单片机·学习·pcb工艺
YxVoyager7 小时前
GAMES101学习笔记(五):Texture 纹理(纹理映射、重心坐标、纹理贴图)
笔记·学习·图形渲染
徐某人..7 小时前
ARM嵌入式学习--第十天(UART)
arm开发·单片机·学习·arm
Buring_learn7 小时前
代理模式 -- 学习笔记
笔记·学习·代理模式