go定时器NewTicker&NewTimer

1.NewTimer:

func NewTimer(d Duration) *Timer {}

d时间段后触发

for {

select {

case <-t.C:

fmt.Println("timer触发")

if 循环 {

t.Reset(delat)

}

case

return

}

}


NewTimer是延迟d时间后触发,如果需要循环则需要Reset。NewTimer的延迟时间并不是精确、稳定的,比如设置30ms,有可能会35、40ms后才触发,即使在系统资源充足的情况下,所以一个循环的timer在60ms内并不能保证会触发2两次,而ticker会。

2.NewTicker:

func NewTicker(d Duration) *Ticker {}

每隔时间段 d 就向该通道发送当时的时间;

go func(timer *Timer) {

defer timer.t.Stop()

for {

select {

case <-timer.t.C:

fmt.Println("ticker 触发")

case <-timer.done:

fmt.Println("ticker 关闭")

return

}

}

}(t)

它会调整时间间隔或者丢弃 tick 信息以适应反应慢的接者,所以回调触发不是稳定的,有可能在小于d的时间段触发,也有可能大于d的时间段触发,即使应用什么都不做。但在一段时间内,触发次数是保证的,比如在系统资源充足的情况下,设定触发间隔30ms,上一ticket触发间隔是44ms,下一触发间隔可能就是16ms,所以60ms内还是会触发两个ticket。


相似处:都可以实现一个定时器,timer需要每次reset时间。

区别:ticker的稳定性不如timer,一个空转的go程序,tickter也是不稳定的,触发间隔并不会稳定在d时间段,在ms级别上;而timer相对稳定,但也不是绝对的,timer也会在大于d的时间后触发。

综上所述,在ms级别定期刷新的定时器,ticket不够稳定但触发次数在一段时间内是固定的(也不是肯定固定,任务处理耗时非常大),timer相对稳定,但总有几个帧会在大于d的时间后触发,导致时间间隔累计值与实际时间戳差值误差越来越大。

所以如果想使用正确的刷新时间,建议使用NewTimer结合时间戳差值来保证程序刷新的正确性,不要利用d的累加或类减作为时间计算因子。

你可能感兴趣的:(go定时器NewTicker&NewTimer)