当需要提前取消定时任务的时候,不能直接关闭定时器。
例:
package main
import (
"fmt"
"time"
)
func run(t *time.Timer) {
<-t.C
fmt.Println("Timer has expired.")
}
func main() {
t := time.NewTimer(3 * time.Second)
fmt.Println("Timer start.")
go run(t)
//t.Stop() // 停止定时器会导致定时任务无法触发
t.Reset(0) // 重置定时器时间为0 立即触发定时任务
time.Sleep(10 * time.Second)
fmt.Println("main exit.")
}
原因:
Golang的Timer实际的实现的方式是以一个小顶堆来维护的Timer集合并循环检查,当到时间后会弹出到Timer的管道(channel)中。
如果这个时候使用 timer.Stop() 会导致管道关闭而定时器申请的管道(channel)并未关闭。这样会导致定 run 方法一直阻塞再 <- t.c