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);
            }
        }
    }
}
相关推荐
魔法阵维护师2 小时前
从零开发游戏需要学习的c#模块,第十章(设计模式入门)
学习·游戏·设计模式·c#
GEO从入门到精通2 小时前
GEO学习能帮我提高AI搜索排名吗?
人工智能·学习
ᰔᩚ. 一怀明月ꦿ2 小时前
MySQL 学习目标
学习·mysql·adb
吃好睡好便好2 小时前
用if…end…语句计算分段函数
开发语言·人工智能·学习·算法·matlab
爱睡懒觉的焦糖玛奇朵2 小时前
【从视频到数据集:焦糖玛奇朵的魔法工具Video To YOLO Dataset】
人工智能·python·学习·yolo·音视频
Dust-Chasing3 小时前
Claude Code源码剖析 - Phase3
开发语言·人工智能·学习
振浩微433射频芯片4 小时前
告别“喊破嗓”:深度解析433MHz射频在宠物训练器中的核心应用与选型
单片机·嵌入式硬件·物联网·学习·宠物
知识分享小能手4 小时前
Flask入门学习教程,从入门到精通, Flask模板 — 完整知识点与案例代码 (2)
python·学习·flask
humors2214 小时前
突破学习瓶颈:十个需要克服的障碍
大数据·学习·程序人生
GEO从入门到精通4 小时前
在哪里能买到GEO学习工具或课程?
人工智能·学习