当前位置: 首页 > article >正文

go系列之 cron 表达式

一、简介

       robfig/cron 是一个用于 Go 语言的定时任务调度库,它允许开发者以类似于 Unix/Linux 系统中的 cron 守护进程的方式来定义和管理周期性任务。

二、使用教程

c := cron.New()
c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") })
c.AddFunc("@hourly",      func() { fmt.Println("Every hour") })
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") })
c.Start()
..
// Funcs are invoked in their own goroutine, asynchronously.
...
// Funcs may also be added to a running Cron
c.AddFunc("@daily", func() { fmt.Println("Every day") })
..
// Inspect the cron job entries' next and previous run times.
inspect(c.Entries())
..
c.Stop()  // Stop the scheduler (does not stop any jobs already running).

三、实现原理

3.1 entry 结构体
type Entry struct {
  
  ID EntryID

  // 本Entry的调度时间,不是绝对时间,在生成entry时会计算出来
  Schedule Schedule

  Next time.Time

  // WrappedJob 是真实执行的Job实体
  WrappedJob Job

}
3.2 Run 实现原理
// access to the 'running' state variable.
func (c *Cron) run() {
	c.logger.Info("start")
 
	now := c.now()
	for _, entry := range c.entries {
		entry.Next = entry.Schedule.Next(now)
		c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next)
	}
 


 
	for {
            		// Determine the next entry to run.
		// 将定时任务执行时间进行排序,最近最早执行的放在前面
		sort.Sort(byTime(c.entries))
 
		var timer *time.Timer
	    if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
			// If there are no entries yet, just sleep - it still handles new entries
			// and stop requests.
			timer = time.NewTimer(100000 * time.Hour)
		} else {
			// 生成一个定时器,距离最近的任务时间到时 触发定时器的channel,发送通知
			timer = time.NewTimer(c.entries[0].Next.Sub(now))
		}
			select {
			// 定时时间到了,执行定时任务,并设置下次执行的时刻
			case now = <-timer.C:
				now = now.In(c.location)
				c.logger.Info("wake", "now", now)
 
				// Run every entry whose next time was less than now
				//对每个定时任务尝试执行
				for _, e := range c.entries {
					if e.Next.After(now) || e.Next.IsZero() {
						break
					}
					c.startJob(e.WrappedJob)
					e.Prev = e.Next
					e.Next = e.Schedule.Next(now)
					c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)
				}
			//新增的定时任务添加到 任务列表中
			case newEntry := <-c.add:
				timer.Stop()
				now = c.now()
				newEntry.Next = newEntry.Schedule.Next(now)
				c.entries = append(c.entries, newEntry)
				c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next)
	
 
			break
		}
	}



http://www.kler.cn/a/296692.html

相关文章:

  • 如何在实际应用中优化AI大模型性能
  • 纯CSS实现卡片欢动效果
  • 关于腾讯IM消息ID不统一的问题?服务端的MsgKey和前端的msgID不一样
  • 强大的EmotiVoice:易魔声 : 多音色提示控制TTS
  • 微信小程序登录与获取手机号 (Python)
  • 基于Android Studio的行程记录APK开发指南(三)---界面设计及两种方法获取用户位置
  • AI在医学领域:MIL回归用于前列腺癌复发预测
  • Linux 性能调优之CPU上下文切换
  • halcon 畸变矫正算子 VectorToAnison
  • lambda 表达式(匿名函数)的具体应用和使用场景
  • FxFactory 8 for Mac 视觉特效插件包安装
  • 【华为笔试2】
  • 【深度学习】LSTM模型,GRU模型计算公式及其优缺点介绍
  • Leetcode面试经典150题-2.两数相加
  • 基于Spring Boot构建一个点餐系统
  • 哥伦比亚TV:重塑影视娱乐版图,开启全球文化共鸣之旅
  • 部署FileBeat采集日志发送到Kafka集群服务器
  • String、StringBuffer、StringBuilder的区别和用法
  • 数据库的操作:SQL语言的介绍
  • 机器学习之 PCA降维