这是我参与「第五届青训营 」伴学笔记创作活动的第 11 天
这是我参与「第五届青训营 」伴学笔记创作活动不水的第 2 天(可能是假的)
我在github上找到了go实现的时间轮算法,把他fork来研究研究.本来代码全糊在一个代码里,这样子是不适合我这种小白阅读的,所以我把代码按功能拆解了一下: github.com/Greenery-S/… 各位看官可以看看,拆的很清晰了,肯定不亏.
这里的时间轮是课中讲解的带count的时间轮,是一种单轮的设计.假如你的时间轮有3600个时间槽,每个时间槽间隔1s,那么它转一轮也就是3600s=1小时.
那如果有一个定时任务是2小时1秒执行呢? 那么这个任务会被挂载到第一个时间槽且cirle记为2.这意味着:
- (1s):当时间轮第一次走到一秒的时候,这个任务不会被执行,circle-1=1;
- (1小时1s):当时间轮转了一圈,再一次走到一秒的时候,这个任务也不会被执行,circle-1=0;
- (2小时1s):当时间轮转了一圈,再一次走到一秒的时候,circle==0,任务也被执行了.
源码拆解后结构如下:
- entity.go //定义实体类型
- init.go //New时间轮对象
- api.go //初始化时间轮,关闭时间轮api
- tick.go //时间轮转,执行任务
- task.go //添加新任务
- remove.go //删除任务
任务管理中心是一个select-case:
func (tw *TimeWheel) start() {
for {
select {
case <-tw.ticker.C://时间轮转,执行任务
tw.tickHandler()
case task := <-tw.addTaskChannel://添加新任务
tw.addTask(&task)
case key := <-tw.removeTaskChannel:
tw.removeTask(key)
case <-tw.stopChannel://删除任务
tw.ticker.Stop()
return
}
}
}
go语言的gorutine和channel真的大爱,非常的精妙,非常的优雅,漂亮滴很那! 未来我会深入学学<concurrency in go>这本书.
我尝试在这个基础上做一个分层时间轮,但总是报错"死锁",我很不解,暂时先这样吧.未来有时间我会试着重构一个分层轮的(不负责任挖坑..).