cron格式: 分 时 日 月 周

每隔5分钟执行1次: */5 * * * * echo hello > /tmp/x.log

每隔1-5分钟执行1次: 1-5 * * * * echo hello > /tmp/x.log

每天10点整、22点整执行1次: 0 10,22 * * * echo hello > /tmp/x.log

每隔1-5分钟执行1次: 1-5 * * * * echo hello > /tmp/x.log


Parse():解析与校验Cron表达式 Next():根据当前时间,计算下次调度时间

package main

import (
	"fmt"
	"github.com/gorhill/cronexpr"
	"time"
)

func main()  {
	var (
		expr *cronexpr.Expression
		err error
		now time.Time
		nextTime time.Time
	)

	//每隔5分钟执行一次(这个库支持7位,精确到秒、年)
	if expr, err = cronexpr.Parse("*/5 * * * * * *"); err != nil {
		fmt.Println(err)
		return
	}

	//当前时间
	now = time.Now()

	//下次调度时间
	nextTime = expr.Next(now)

	//等待这个定时器超时
	time.AfterFunc(nextTime.Sub(now), func() {
		fmt.Println("被调度了:", nextTime)
	}) //下次时间减去当前时间

	time.Sleep(10 * time.Second)

}

调用一个cron 输出:被调度了: 2019-04-19 17:00:30 +0800 CST

package main

import (
	"fmt"
	"github.com/gorhill/cronexpr"
	"time"
)

//代表一个任务
type CronJob struct {
	expr *cronexpr.Expression
	nextTime time.Time //expr.Next(time.Now())就可以得到下一次调度时间
}

func main()  {
	//需要有1个调度协程,它定时检查所有Cron任务,谁过期了就执行谁

	var (
		cronJob *CronJob
		expr *cronexpr.Expression
		now time.Time
		scheduleTable map[string] *CronJob //key:任务名字,
	)

	scheduleTable = make(map[string]*CronJob)

	//当前时间
	now = time.Now()

	//定义第一个cronjob
	expr = cronexpr.MustParse("*/5 * * * * * *")
	cronJob = &CronJob{
		expr: expr,
		nextTime: expr.Next(now),
	}
	//任务注册到了调度表
	scheduleTable["job1"] = cronJob

	//定义第二个cronjob
	expr = cronexpr.MustParse("*/5 * * * * * *")
	cronJob = &CronJob{
		expr: expr,
		nextTime: expr.Next(now),
	}
	//任务注册到了调度表
	scheduleTable["job2"] = cronJob

	//启动调度协程
	go func() {
		var (
			jobName string
			cronJob *CronJob
			now time.Time
		)
		//定时检查任务调度表是否有到期的
		for {
			now = time.Now()
			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 {
			//睡眠100毫秒(不让它占用过多cpu)
			case <- time.NewTimer(100 * time.Millisecond).C: //将在100毫秒可读,返回
			}

		}
	}()

	time.Sleep(100 * time.Second)

}

调用多个cron,按时间间隔输出: 执行: job1 job1 下次执行时间: 2019-04-19 17:31:20 +0800 CST job2 下次执行时间: 2019-04-19 17:31:20 +0800 CST 执行: job2 执行: job1 job1 下次执行时间: 2019-04-19 17:31:25 +0800 CST 执行: job2 job2 下次执行时间: 2019-04-19 17:31:25 +0800 CST 执行: job1 job1 下次执行时间: 2019-04-19 17:31:30 +0800 CST job2 下次执行时间: 2019-04-19 17:31:30 +0800 CST 执行: job2 ......