用golang实现一个定时器任务队列实例

2020-01-28 12:58:45王旭


func (one *OnceCron) Start() {
 //初始化的時候加入一個一年的長定時器,間隔1小時執行一次
 task := getTaskWithFuncSpacing(3600, time.Now().Add(time.Hour*24*365).Unix() , func() {
 log.Println("It's a Hour timer!")
 }) //为了代码格式markdown 里面有个括号我改成全角了
 one.tasks = append(one.tasks, task)
 go one.run() //协成执行 防止主进程被阻塞
}

执行部分应该是重点的,我的理解是,分成三部:

    首先获得一个最先执行的任务 然后产生一个定时器,用于执行任务 进行阻塞判断,获取我们要进行的操作

func (one *OnceCron) run() {

 for {
    //第一步 获取任务
 now := time.Now() //获取到当前时间
 task, key := one.GetTask() //获取最近的一个任务的执行时间
 i64 := task.RunTime - now.Unix() //任务执行和当前时间的差

 var d time.Duration
 if i64 < 0 { //如果任务时间已过期,将执行时间改成现在并且利马执行
 one.tasks[key].RunTime = now.Unix() 
 one.doAndReset(key)
      continue
 } else { //否则,获取距离执行开始的间隔时间
 d = time.Unix(task.RunTime, 0).Sub(now)
 }
    //第二步 产生定时器
 timer := time.NewTimer(d) 

 //第三步 捕获定时器或者其他事件
 for {
 select { 
      //当定时器到了执行时间时,执行当前任务并关闭定时器
 case <-timer.C:
 one.doAndReset(key)
 if task != nil {
  go task.Job.Run()
  timer.Stop()
 }

 //当外部添加了任务时,关闭当前定时器
 case <-one.add:
 timer.Stop()
 //当外部要删除一个任务时,删除ID为uuidstr的任务
 case uuidstr := <-one.remove:
 one.removeTask(uuidstr)
 timer.Stop()
 //当遇到要关闭整个定时器任务时
 case <-one.stop:
 timer.Stop()
 return
 }

 break
 }
 }
}

后记

这个文章纯粹为笔记分析类的文章,旨在分析我碰到一个需求是如何通过分析过程来产生我们需要的代码的。

源码地址:timing 一个任务队列

应用地址:一个应用于谷歌消息推送的转发中间件

参考源码:GOLANG实现crontab功能

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持易采站长站。