Ticker 在 time.sleep() 中的行为

Posted

技术标签:

【中文标题】Ticker 在 time.sleep() 中的行为【英文标题】:Ticker's behavior with time.sleep() 【发布时间】:2022-01-18 11:32:54 【问题描述】:

代码:

func main() 
    fmt.Println(time.Now())
    ticker := time.NewTicker(100 * time.Millisecond)
    done := make(chan bool)

    go func() 
        time.Sleep(900 * time.Millisecond)
        for 
            select 
            case <-done:
                return
            case t := <-ticker.C:
                fmt.Println("Tick at", t)
            
        
    ()
    time.Sleep(1600 * time.Millisecond)
    ticker.Stop()
    done <- true
    fmt.Println("Ticker stopped")

输出:

2021-12-15 17:00:44.2506052 +0800 +08 m=+0.002777301
Tick at 2021-12-15 17:00:44.3916764 +0800 +08 m=+0.143848501
Tick at 2021-12-15 17:00:45.2913066 +0800 +08 m=+1.043478701
Tick at 2021-12-15 17:00:45.4007827 +0800 +08 m=+1.152954801
Tick at 2021-12-15 17:00:45.4930864 +0800 +08 m=+1.245258501
Tick at 2021-12-15 17:00:45.6021253 +0800 +08 m=+1.354297401
Tick at 2021-12-15 17:00:45.6980372 +0800 +08 m=+1.450209301
Tick at 2021-12-15 17:00:45.7929148 +0800 +08 m=+1.545086901
Tick at 2021-12-15 17:00:45.901921 +0800 +08 m=+1.654093101
Ticker stopped

问题: 我如何解释结果?更具体地说:

    为什么 goroutine 中的 sleep 会暂停 ticker 而 main 例程中的 sleep 不会? ticker.C 是否没有缓冲所以没有 16 个滴答声? 为什么第一个刻度的 m=+0.143848501?

【问题讨论】:

+m= 是关于“单调时钟”的,在包时间文档中有解释。 @Volker 我的意思是为什么它是 0.1+ 而不是 1+? 【参考方案1】:
    goruotine 中的睡眠不会暂停代码,它会延迟第一次打印值的时刻。 ticker.C 的缓冲区为 1。根据代码中的 cmets:
    // Give the channel a 1-element time buffer.
    // If the client falls behind while reading, we drop ticks
    // on the floor until the client catches up.

所以那里只有一个缓冲值。

    第一个报价大约在报价单持续时间第一次经过约 100 毫秒的那一刻写入通道。然后跳过其他滴答声,因为ticker.C 中的缓冲区已满,并被丢弃,直到通道在 time 后解除阻塞。睡眠过去了,所以我们有大约 900 毫秒的跳跃。

【讨论】:

以上是关于Ticker 在 time.sleep() 中的行为的主要内容,如果未能解决你的问题,请参考以下文章

golang中定时器实现,Ticker,Timer

[golang]定时器

time.sleep 不适用于范围或列表中的每个项目[重复]

在多线程程序中添加 time.sleep 解决了 python 中的 UnicodeDecodeError

time.sleep -- 休眠线程或进程?

更准确的 time.sleep 用于 Python 3 中的短(毫秒)延迟? [复制]