昨天看到了select timeAfter可以很方便的实现接口超时,今天再针对timer使用时需要注意的几个陷阱总结一下。
go里面定时任务是在时间推里面,定时任务到期之前,是不会被gc清理掉的。这样如果短时间内创建大量定时任务,就会造成内存泄漏。
for {
timerC := time.After(2 * time.Second)
//timerC 每次都是重新创建的,什么意思呢?简单说来,当 select 成功监听 ch 并进入它的处理分支,下次循环 timerC 重新创建了,时间肯定就重置了。
select {
//如果有多个 case 都可以运行,select 会随机公平选择出一个执行。其余的则不会执行
case num := <-ch:
fmt.Println("get num is", num)
case <-timerC:
//等价于 case <-time.After(2 * time.Second)
fmt.Println("time's up!!!")
//done<-true
}
}
这样的写法在for循环里用time.After 典型的内存泄漏,time.After 每次会产生一个新的定时器。解决办法就是采用timer代替,每次重置timer。
idleDuration := 2 * time.Second
idleDelay := time.NewTimer(idleDuration)
defer idleDelay.Stop()
for {
idleDelay.Reset(idleDuration)
select {
case num := <-ch:
fmt.Println("get num is", num)
case <-idleDelay.C:
fmt.Println("time's up!!!")
//done<-ture
}
}
来源:CSDN
作者:哆啦a梦蓝胖子
链接:https://blog.csdn.net/qq_34675369/article/details/103516862