Timer && Ticker

Which one is wrong???

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
func Tick() {
tick := time.Tick(10 * time.Microsecond)
for {
select {
case <- tick:
fmt.Printf("Tick")
}
}
}
func Tick() {
for {
select {
case <-time.Tick(10 * time.Millisecond):
fmt.Println("ttt")
}
}
}

熟悉Golang的应该都用过Timer、Ticker、After,这里记录一下在使用中遇到的坑。

在使用Timer时,创建过多的Timer导致CPU增高。具体原因可查看golang语言Api系统中CPU功耗优化300倍的过程

如何正确使用

After 一次性定时器

1
2
3
4
5
6
7
8
func AfterFunc() {
for {
select {
case <-time.After(1 * time.Millisecond):
fmt.Println("After")
}
}
}

Tick 永久定时器

1
2
3
4
5
6
7
8
9
func Tick() {
tick := time.Tick(10 * time.Microsecond)
for {
select {
case <- tick:
fmt.Printf("Tick")
}
}
}

错误的使用方式

1
2
3
4
5
6
7

for {
select {
case <-time.Tick(10 * time.Millisecond):
fmt.Println("ttt")
}
}

这种方式会导致创建无数个timer协程,导致timer处理线程占用大量CPU资源。

如何优雅的关闭Timer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func startTimer(f func()) chan struct{} {
done := make(chan struct{}, 1)
go func() {
timer := time.NewTicker(5 * time.Minute)
defer timer.Stop()
for {
select {
case <-timer.C:
f()
case <-done:
return
}
}
}()
return done
}
// 使用方法
done := startTimer(a.authenticate)
...
close(done)