Go:定时执行任务time.sleep和time.tick的优劣 (2)

//go:linkname timeSleep time.Sleep
func timeSleep(ns int64) {
*t = timer{} //创建一个定时任务
t.when = nanotime() + ns //计算定时任务的执行时间点
t.f = goroutineReady //执行方法
tb.addtimerLocked(t) //加入timer堆,并在timer定时任务执行协程中等待被执行
goparkunlock(&tb.lock, "sleep", traceEvGoSleep, 2) //睡眠,等待定时任务协程通知唤醒
}
读了sleep的核心代码之后,是不是突然发现和Tick函数的内容很类似,都创建了timer,并加入了定时任务处理协程。神奇之处就在于,实际上这两个函数产生的timer都放入了同一个timer堆,都在定时任务处理协程中等待被处理。

优劣性对比,使用建议
现在我们知道了,Tick,Sleep,包括time.After函数,都使用的timer结构体,都会被放在同一个协程中统一处理,这样看起来使用Tick,Sleep并没有什么区别。

实际上是有区别的,Sleep是使用睡眠完成定时任务,需要被调度唤醒。Tick函数是使用channel阻塞当前协程,完成定时任务的执行。当前并不清楚golang 阻塞和睡眠对资源的消耗会有什么区别,这方面不能给出建议。

但是使用channel阻塞协程完成定时任务比较灵活,可以结合select设置超时时间以及默认执行方法,而且可以设置timer的主动关闭,以及不需要每次都生成一个timer(这方面节省系统内存,垃圾收回也需要时间)。

所以,建议使用time.Tick完成定时任务。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwfys.html