6)L,W,#
Go中没有L,W,#的用法,下文作解释。
cron举例说明
每隔5秒执行一次:*/5 * * * * ?
每隔1分钟执行一次:0 */1 * * * ?
每天23点执行一次:0 0 23 * * ?
每天凌晨1点执行一次:0 0 1 * * ?
每月1号凌晨1点执行一次:0 0 1 1 * ?
在26分、29分、33分执行一次:0 26,29,33 * * * ?
每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?
下载安装
控制台输入 go get github.com/robfig/cron 去下载定时任务的Go包,前提是你的 $GOPATH 已经配置好
源码解析
文件目录讲解
constantdelay.go #一个最简单的秒级别定时系统。与cron无关
constantdelay_test.go #测试
cron.go #Cron系统。管理一系列的cron定时任务(Schedule Job)
cron_test.go #测试
doc.go #说明文档
LICENSE #授权书
parser.go #解析器,解析cron格式字符串城一个具体的定时器(Schedule)
parser_test.go #测试
README.md #README
spec.go #单个定时器(Schedule)结构体。如何计算自己的下一次触发时间
spec_test.go #测试
cron.go
结构体:
// Cron keeps track of any number of entries, invoking the associated func as
// specified by the schedule. It may be started, stopped, and the entries may
// be inspected while running.
// Cron保持任意数量的条目的轨道,调用相关的func时间表指定。它可以被启动,停止和条目,可运行的同时进行检查。
type Cron struct {
entries []*Entry // 任务
stop chan struct{} // 叫停止的途径
add chan *Entry // 添加新任务的方式
snapshot chan []*Entry // 请求获取任务快照的方式
running bool // 是否在运行
ErrorLog *log.Logger // 出错日志(新增属性)
location *time.Location // 所在地区(新增属性)
}
// Entry consists of a schedule and the func to execute on that schedule.
// 入口包括时间表和可在时间表上执行的func
type Entry struct {
// 计时器
Schedule Schedule
// 下次执行时间
Next time.Time
// 上次执行时间
Prev time.Time
// 任务
Job Job
}
关键方法:
// 开始任务
// Start the cron scheduler in its own go-routine, or no-op if already started.
func (c *Cron) Start() {
if c.running {
return
}
c.running = true
go c.run()
}
// 结束任务
// Stop stops the cron scheduler if it is running; otherwise it does nothing.
func (c *Cron) Stop() {
if !c.running {
return
}
c.stop <- struct{}{}
c.running = false
}
// 执行定时任务
// Run the scheduler.. this is private just due to the need to synchronize
// access to the 'running' state variable.
func (c *Cron) run() {
// Figure out the next activation times for each entry.
now := time.Now().In(c.location)
for _, entry := range c.entries {
entry.Next = entry.Schedule.Next(now)
}
// 无限循环
for {
//通过对下一个执行时间进行排序,判断那些任务是下一次被执行的,防在队列的前面.sort是用来做排序的
sort.Sort(byTime(c.entries))
var effective time.Time
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.
effective = now.AddDate(10, 0, 0)
} else {
effective = c.entries[0].Next
}
timer := time.NewTimer(effective.Sub(now))
select {
case now = <-timer.C: // 执行当前任务
now = now.In(c.location)
// Run every entry whose next time was this effective time.
for _, e := range c.entries {
if e.Next != effective {
break
}
go c.runWithRecovery(e.Job)
e.Prev = e.Next
e.Next = e.Schedule.Next(now)
}
continue
case newEntry := <-c.add: // 添加新的任务
c.entries = append(c.entries, newEntry)
newEntry.Next = newEntry.Schedule.Next(time.Now().In(c.location))
case <-c.snapshot: // 获取快照
c.snapshot <- c.entrySnapshot()
case <-c.stop: // 停止任务
timer.Stop()
return
}
// 'now' should be updated after newEntry and snapshot cases.
now = time.Now().In(c.location)
timer.Stop()
}
}









