项目中TimerService的代码分享

上一篇文章《gorutine不立即执行的解决办法》中提到了timerService这东西,其实就是对time.Timer的一个封装,只是可以用来管理很多的timer,我首先给timerService定义了一些接口

1
2
3
4
5
type TimerService interface {
RegNotify(notify chan<- time.Time, delay time.Duration, loop bool) (done chan<- bool)
Close()
}

这里有一个注册通知的接口,第一个参数:Notify 实际上是chan被触发的时候放进去当前时间,第二个参数是延迟多久触发,第三个参数是是否循环通知。

返回的参数是停止这个timer的chan

下面看看实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
type _timerService struct {
isStop bool
dones map[chan bool]*time.Timer
}
func (this *_timerService) RegNotify(notify chan<- time.Time, delay time.Duration, loop bool) chan<- bool {
if this.isStop {
return nil
}
_done := make(chan bool)
key := time.Now().Unix()
go func(key int64, done chan bool) {
timer := time.NewTimer(delay)
this.dones[_done] = timer
isStop := false
for !isStop {
select {
case <-timer.C:
notify <- time.Now()
if !loop {
timer.Stop()
close(done)
}
timer.Reset(delay)
break
case <-done:
isStop = true
break
}
}
timer.Stop()
delete(this.dones, _done)
}(key, _done)
return _done
}
func (this *_timerService) Close() {
this.isStop = true
for done, timer := range this.dones {
timer.Stop()
close(done)
}
}

其实看上来还是比较简单的,起了一个 goroutine, 然后等待这个 timer 时间到触发向 notify 放入当前时间的事件,接着判断是否需要继续循环执行还是退出.

这里需要用到一个 goroutine, 但是这个是协程级别的,基本上没有什么消耗,最后关闭 timeer 我用的是 close(channel)的做法,这种做法不用担心 chen被多个 goroutine 调用引起某个 timer 没有被完全关闭.

具体 chennel 的特性我也不再复述,网上很多,这里真的要吐槽一下,我今天搜索 influxDB 的原理的时候,中文全网都是如果安装,内容几乎一样,你妹的,能不能有点原创的东西啊,都抄来抄去的

坚持原创技术分享,您的支持将鼓励我继续创作!