安装Cronexpr包:
go get -u github.com/gorhill/cronexpr
这个包支持七位时间控制
*(秒) *(分) *(时) *(日) *(月) *(周) *(年)
栗子:
每5秒执行一次: */5 * * * * * *
一个简单的小栗子
package main
import (
"fmt"
"github.com/gorhill/cronexpr"
"time"
)
//* * * * * * *
//秒 分 时 日 月 周 年
func main() {
var expr *cronexpr.Expression
var err error
//每5秒执行一次
if expr, err = cronexpr.Parse("*/5 * * * * * *");err != nil{
fmt.Println("err=", err)
return
}
//当前时间
now := time.Now()
fmt.Println("now=",now)
nextTime := expr.Next(now)
fmt.Println("nextTime=", nextTime)
time.AfterFunc(nextTime.Sub(now), func() {
fmt.Println("被调用了")
})
time.Sleep(6*time.Second)
}
输出
now= 2020-05-03 00:58:48.6350048 +0800 CST m=+0.008000001 nextTime= 2020-05-03 00:58:50 +0800 CST 被调用了
注意:这里每5秒也好,每3分钟也好,都不是以现在的时间计时的:
例如:
每5秒:假设现在12:00:02,下次执行时间将会是12:00:05,他会从0秒开始累加计算下次时间,而不是现在的秒数
每3分钟:假设现在12:00:02,下次执行时间将会是12:03:00,他会从0分开始累加计算,并且秒数归零
一个并发多任务的定时任务小案例
package main
import (
"fmt"
"github.com/gorhill/cronexpr"
"time"
)
//代表任务
type CronJob struct {
expr *cronexpr.Expression
nextTime time.Time
}
func main() {
//创建map,用于存储多个定时任务
scheduleTable := make(map[string]*CronJob)
//当前时间
now := time.Now()
expr, _ := cronexpr.Parse("*/5 * * * * * *")
cronJob := &CronJob{
expr:expr,
nextTime:expr.Next(now),
}
scheduleTable["job1"] = cronJob
expr, _ = cronexpr.Parse("*/4 * * * * * *")
cronJob = &CronJob{
expr:expr,
nextTime:expr.Next(now),
}
scheduleTable["job2"] = cronJob
go func() {
for{
now := time.Now()
//遍历map,取出每一个定时任务,检查是否过期
for jobName, cronJob := range scheduleTable{
//当前定时任务下次执行的时间在当前时间之前或者等于当前时间
if cronJob.nextTime.Before(now)||cronJob.nextTime.Equal(now){
//开启协程,执行定时任务
go func(jobName string) {
fmt.Println("执行:", jobName)
}(jobName)
//计算下一次调度的时间
cronJob.nextTime = cronJob.expr.Next(now)
fmt.Println(jobName, "下次执行时间:",cronJob.nextTime)
}
}
select {
case <-time.NewTimer(100 * time.Millisecond).C:
}
}
}()
time.Sleep(100*time.Second)
}