Closed
Description
Leaf timer
Go 语言标准库提供了定时器的支持:
func AfterFunc(d Duration, f func()) *Timer
AfterFunc 会等待 d 时长后调用 f 函数,这里的 f 函数将在另外一个 goroutine 中执行。Leaf 提供了一个相同的 AfterFunc 函数,相比之下,f 函数在 AfterFunc 的调用 goroutine 中执行,这样就### 避免了同步机制的使用:
skeleton.AfterFunc(5 * time.Second, func() {
// ...
})
另外,Leaf timer 还支持 cron 表达式,用于实现诸如“每天 9 点执行”、“每周末 6 点执行”的逻辑。
更加详细的用法可以参考 leaf/timer。
Activity
name5566 commentedon Nov 13, 2018
正如文档所述的那样,标准库的 AfterFunc 中的 f 函数在另外一个 goroutine 中执行,所以,f 中的相关代码需要考虑使用同步机制。
jjjjilyf commentedon Nov 14, 2018
谢谢回答,看到了源代码如下:
`// AfterFunc waits for the duration to elapse and then calls f
// in its own goroutine. It returns a Timer that can
// be used to cancel the call using its Stop method.
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
when: when(d),
f: goFunc,
arg: f,
},
}
startTimer(&t.r)
return t
}
func goFunc(arg interface{}, seq uintptr) {
go arg.(func())()
}`
可能我功力还不够,不太能想象的到,这个同步机制的使用场景。
现在的使用场景是用Skeleton.AfterFunc做帧同步的服务器驱动,每隔60毫秒发送一次消息驱动客户端帧逻辑帧处理,结果发现skeleton.AfterFun的的时间间隔并不稳定,99.N%以上都是60毫秒间隔左右,但有时候会跳到60毫秒的2倍或者3倍以上,目前的解决方法是:
`duration := time.Duration((b.bLogicInterval) * int64(time.Millisecond))
b.syncTimer = time.NewTimer(duration)
暂时未发现问题。
name5566 commentedon Nov 14, 2018
不使用同步可能引起问题,一定概率发生(可能通常都不发生),可能在用户量比较大的时候才出现。你发现的 Leaf 的 timer 会延时是因为某一些情况下,定时器到了触发时间了,但是现在还没机会执行,所以它就排队等待(可以认为是当前 goroutine 繁忙,需要处理其他代码),而 go 的 timer 额外开了一个 goroutine 来执行,所以无需等待(一定程度上来说是)。
实际上,这个问题是服务器帧率控制的问题。而帧率控制其实是动态的,而不是固定一个时间间隔,你可以看看 https://github.com/mangos/mangosd/blob/master/WorldRunnable.cpp#L78 的实现方法,思考一下。在 Leaf 中最好的帧率控制应该实现在 select 的 default 中。更多的东西就需要你自己探索了
jjjjilyf commentedon Dec 5, 2018
多谢5566大神的指点,受益匪浅。看到的有点晚。。。
jjjjilyf commentedon Dec 5, 2018
Thanks♪(・ω・)ノ