package main
import (
"time"
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(1)
TestTicker(wg)
wg.Wait()
}
func TestTicker(wg sync.WaitGroup) {
calDuration := func(duration time.Duration) time.Duration {
now := time.Now()
return now.Truncate(duration).Add(duration).Sub(now)
}
go func(){
t := time.NewTimer(calDuration(time.Minute))
for {
<-t.C
fmt.Println(time.Now())
t.Reset(calDuration(time.Minute))
}
wg.Done()
}()
}
有时会每分钟滴答两次,因为持续时间可能会缩短。真的很奇怪有人可以帮我吗。谢谢
我只是在调用TestTicker时使用waitgroup来保存主要功能。
我正在MacOS上运行测试代码
2018-07-19 14:36:00.003887996 +0800 CST m=+24.916092657
2018-07-19 14:37:00.002985076 +0800 CST m=+84.917119245
2018-07-19 14:38:00.001214551 +0800 CST m=+144.917278207
2018-07-19 14:39:00.000418561 +0800 CST m=+204.918411736
2018-07-19 14:39:59.999490194 +0800 CST m=+264.919412884
2018-07-19 14:40:00.000167519 +0800 CST m=+264.920090231
2018-07-19 14:40:59.99914446 +0800 CST m=+324.920996684
2018-07-19 14:41:00.000247228 +0800 CST m=+324.922099488
答案 0 :(得分:-1)
计时器精度可能会因操作系统,硬件和CPU负载而异。虚拟机在提供准确的计时器方面似乎特别糟糕(请参见https://github.com/golang/go/issues/14410)。不幸的是,您没有提到在什么环境中运行此代码。
如果您可以忍受不准确的情况,并且仍然需要代码在整整一分钟左右做某事,则代码会中断,因为间隔太短(14:39:59.999490194
仅比{{1}小500µs }),14:40
将使其等待几微秒,直到下一整分钟。为了解决这个问题,您需要使用calDuration
而不是Duration.Round
。
也不要忘记t.C返回计时器触发的时间,因此您需要在对Duration.Truncate
的调用中使用此值(这还可以节省昂贵的系统调用)。
calDuration
另一种方法是使用标准库中的func TestTicker(wg *sync.WaitGroup) {
calDuration := func(now time.Time, duration time.Duration) time.Duration {
return now.Round(duration).Add(duration).Sub(now)
}
go func(){
t := time.NewTimer(calDuration(time.Now(), time.Minute))
for {
now := <-t.C
fmt.Println(now)
t.Reset(calDuration(now, time.Minute))
}
wg.Done()
}()
}
并在开始行情自动收录器之前发出适当的睡眠,以使其在一整分钟内进行滴答:
time.Ticker