1.NewTimer:
func NewTimer(d Duration) *Timer {}
d时间段后触发
for {
select {
case <-t.C:
fmt.Println("timer触发")
if 循环 {
t.Reset(delat)
}
case <done:
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的累加或类减作为时间计算因子。
网友评论