Ticker's behavior with time.sleep()

huangapple go评论89阅读模式
英文:

Ticker's behavior with 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,而在主程序中的 sleep 不会?
  2. ticker.C 是非缓冲的,所以为什么不会有 16 个 tick?
  3. 为什么第一个 tick 的 m=+0.143848501?

请注意,我将不会回答关于翻译的问题。

英文:

Code:

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 &lt;-done:
				return
			case t := &lt;-ticker.C:
				fmt.Println(&quot;Tick at&quot;, t)
			}
		}
	}()
	time.Sleep(1600 * time.Millisecond)
	ticker.Stop()
	done &lt;- true
	fmt.Println(&quot;Ticker stopped&quot;)
}

Output:

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

Questions:
How do I interpret the result? More specifically:

  1. Why the sleep in the goroutine will pause the ticker while the sleep in the main routine will not?
  2. Is ticker.C non buffering so there aren't 16 ticks?
  3. Why the first tick has m=+0.143848501?

答案1

得分: 1

  1. 在断头台中的睡眠不会暂停计时器,它只会延迟第一次打印值的时刻。
  2. ticker.C 有一个大小为1的缓冲区。根据代码中的注释:
// 给通道一个1个元素的时间缓冲区。
// 如果客户端在读取时落后,我们会丢弃一些 tick,
// 直到客户端赶上为止。

因此,那里只有一个缓冲值。

  1. 第一个 tick 大约在计时器持续时间首次过去的时刻(约100毫秒左右)被写入通道。其他的 tick 然后被跳过,因为 ticker.C 中的缓冲区已满,并且在 time.Sleep 过后通道解除阻塞之前被丢弃,所以我们有了大约 900 毫秒的跳跃。
英文:
  1. The sleep in the goruotine doesn't pause the ticker, it delays the moment when the value is printed for the first time.
  2. ticker.C has a buffer of 1. According to comments in code:
	// 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.

So there is only one buffered value there.

  1. The first tick is written into the channel roughly around the moment when the ticker duration passes for the first time ~100ms. Other ticks are then skipped because buffer in ticker.C is full and are dropped until the channel is unblocked after time.Sleep passes so we have a jump of ~900 ms.

huangapple
  • 本文由 发表于 2021年12月15日 17:12:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/70361013.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定