Ticker 在 time.sleep() 中的行为

代码:


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

问题:我如何解释结果?进一步来说:

  1. 为什么 goroutine 中的 sleep 会暂停 ticker 而 main 例程中的 sleep 不会?

  2. 是ticker.C 非缓冲所以没有16 个滴答声?

  3. 为什么第一个刻度有 m=+0.143848501?


慕容708150
浏览 122回答 1
1回答

守着星空守着你

goruotine 中的睡眠不会暂停代码,它会延迟第一次打印值的时刻。ticker.C 的缓冲区为 1。根据代码中的注释:&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;Give&nbsp;the&nbsp;channel&nbsp;a&nbsp;1-element&nbsp;time&nbsp;buffer. &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;If&nbsp;the&nbsp;client&nbsp;falls&nbsp;behind&nbsp;while&nbsp;reading,&nbsp;we&nbsp;drop&nbsp;ticks &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;on&nbsp;the&nbsp;floor&nbsp;until&nbsp;the&nbsp;client&nbsp;catches&nbsp;up.所以那里只有一个缓冲值。第一个刻度大约在刻度持续时间第一次经过约 100 毫秒的那一刻被写入通道。然后跳过其他滴答声,因为ticker.C 中的缓冲区已满并被丢弃,直到通道在 time.Sleep 之后被解除阻塞,所以我们有大约 900 毫秒的跳跃。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go