Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Модуль time

Доступно только с флагом функции time.

Утилиты для отслеживания времени.

Этот модуль предоставляет ряд типов для выполнения кода по истечении заданного периода времени.

  • Sleep - это future, который не выполняет работы и завершается в определенный момент времени Instant.

  • Interval - это поток, выдающий значение с фиксированным периодом. Он инициализируется Duration и повторно выдает значение каждый раз, когда длительность истекает.

  • Timeout - оборачивает future или поток, устанавливая верхнюю границу времени, которое ему разрешено выполняться. Если future или поток не завершается вовремя, он отменяется и возвращается ошибка.

Этих типов достаточно для обработки большого количества сценариев, связанных со временем.

Эти типы должны использоваться в контексте Runtime.

Примеры

Ожидание 100 мс и вывод сообщения

#![allow(unused)]
fn main() {
use std::time::Duration;
use tokio::time::sleep;

sleep(Duration::from_millis(100)).await;
println!("100 мс прошло");
}

Требование, чтобы операция занимала не более 1 секунды

#![allow(unused)]
fn main() {
use tokio::time::{timeout, Duration};

async fn long_future() {
    // выполняем работу здесь
}

let res = timeout(Duration::from_secs(1), long_future()).await;

if res.is_err() {
    println!("операция превысила время ожидания");
}
}

Простой пример использования interval для выполнения задачи каждые две секунды

Разница между interval и sleep заключается в том, что interval измеряет время с последнего тика, что означает, что .tick().await может ждать меньше времени, чем указанная для интервала длительность, если между вызовами .tick().await прошло некоторое время.

Если в примере ниже заменить tick на sleep, задача будет выполняться только раз в три секунды, а не каждые две секунды.

#![allow(unused)]
fn main() {
use tokio::time;

async fn task_that_takes_a_second() {
    println!("hello");
    time::sleep(time::Duration::from_secs(1)).await
}

let mut interval = time::interval(time::Duration::from_secs(2));
for _i in 0..5 {
    interval.tick().await;
    task_that_takes_a_second().await;
}
}

Использование таймаута с потоком

#![allow(unused)]
fn main() {
use tokio::time::{timeout, Duration};
use tokio_stream::{self as stream, StreamExt};

let mut stream = stream::iter(1..=10);
let result = timeout(Duration::from_secs(1), async move {
    while let Some(value) = stream.next().await {
        println!("обрабатываем значение: {}", value);
        // Имитация работы
        tokio::time::sleep(Duration::from_millis(200)).await;
    }
}).await;

match result {
    Ok(_) => println!("поток завершился успешно"),
    Err(_) => println!("поток превысил время ожидания"),
}
}

Использование sleep_until для планирования на определенное время

#![allow(unused)]
fn main() {
use tokio::time::{sleep_until, Instant};
use std::time::Duration;

// Запланировать выполнение через 5 секунд от текущего момента
let deadline = Instant::now() + Duration::from_secs(5);
sleep_until(deadline).await;
println!("5 секунд прошло с момента планирования");
}

Реэкспорт

#![allow(unused)]
fn main() {
pub use std::time::Duration;
}

Модули

ИмяФлагиОписание
errorТипы ошибок времени.

Структуры

ИмяОписание
InstantИзмерение монотонно неубывающих часов. Непрозрачно и полезно только с Duration.
IntervalИнтервал, возвращаемый interval и interval_at.
SleepFuture, возвращаемый sleep и sleep_until.
TimeoutFuture, возвращаемый timeout и timeout_at.

Перечисления

ИмяОписание
MissedTickBehaviorОпределяет поведение Interval при пропуске тика.

Функции

ИмяФлагиОписание
advancetest-utilПеремещает время вперед.
intervalСоздает новый Interval, который выдает значения с интервалом period. Первый тик завершается немедленно. Поведение по умолчанию для пропущенных тиков - Burst, но это можно настроить, вызвав set_missed_tick_behavior.
interval_atСоздает новый Interval, который выдает значения с интервалом period, причем первый тик завершается в start. Поведение по умолчанию для пропущенных тиков - Burst, но это можно настроить, вызвав set_missed_tick_behavior.
pausetest-utilПриостанавливает время.
resumetest-utilВозобновляет время.
sleepОжидает, пока не пройдет указанная длительность.
sleep_untilОжидает, пока не будет достигнут указанный крайний срок.
timeoutТребует, чтобы Future завершился до истечения указанной длительности.
timeout_atТребует, чтобы Future завершился до указанного момента времени.

Дополнительные примеры

Настройка поведения при пропущенных тиках

#![allow(unused)]
fn main() {
use tokio::time::{interval, Duration, MissedTickBehavior};

let mut interval = interval(Duration::from_secs(1));
interval.set_missed_tick_behavior(MissedTickBehavior::Skip);

loop {
    interval.tick().await;
    println!("тик");
    // Если эта задача занимает больше 1 секунды, следующие тики будут пропущены
    // до следующего подходящего момента времени
}
}

Комбинирование нескольких таймеров

#![allow(unused)]
fn main() {
use tokio::time::{sleep, timeout, Duration};

async fn complex_operation() -> Result<(), Box<dyn std::error::Error>> {
    // Ожидание 500 мс
    sleep(Duration::from_millis(500)).await;
    
    // Выполнение операции с таймаутом 2 секунды
    let result = timeout(Duration::from_secs(2), async {
        // Длительная операция
        sleep(Duration::from_secs(1)).await;
        "результат операции"
    }).await?;
    
    println!("{}", result);
    Ok(())
}
}