zoukankan      html  css  js  c++  java
  • go之cron使用

    1、cron表达式的基本格式

    在linux中使用过crontab,对定时任务应该就会有所了解,linux中利用crontab -e打开crontab表来添加定时任务,但是只能精确到分钟,go中却可以精确到秒。表达式如下:

     ┌─────────────second 范围 (0 - 60)
     │ ┌───────────── min (0 - 59)
     │ │ ┌────────────── hour (0 - 23)
     │ │ │ ┌─────────────── day of month (1 - 31)
     │ │ │ │ ┌──────────────── month (1 - 12)
     │ │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
     │ │ │ │ │ │                  Saturday)
     │ │ │ │ │ │
     │ │ │ │ │ │
     *  *  *  *  *  *

    2、特殊字符

    星号:匹配所有值

    斜线:增长间隔,*/5表示5 10 15....分钟运行

    逗号:枚举值,1,13,21表示1 13 21分钟运行

    连字符:表示范围,10-15表示10 11 12 13 15分钟运行

    问号:只用于日和星期,表示不指定,可用*替代

    3、go中cron设计思路

    //cron实体
    type Cron struct {
        entries  []*Entry
        stop     chan struct{} //控制Cron实例暂停
        add      chan *Entry   //当Cron已经运行了,增加新的Entity,是通过add该channel实现的
        snapshot chan []*Entry //获取当前所有entity的快照
        running  bool          //是否正在运行中
        ......
    }
    
    //调度实体
    type Entry struct {
        //负责调度当前Entity中的Job执行
        Schedule Schedule
        //Job下一步执行的时间
        Next time.Time
        //Job上一次执行时间
        Prev time.Time
        //要执行的Job
        Job Job
    }
    
    //每一个运行的试题包含一个Job
    type Job interface {
        Run()
    }
    
    //实现Job接口
    type FuncJob func()
    
    //通过简单的run()来实现job
    func (f FuncJob) Run() { f() }
    
    //每个实体包含一个调度器
    type Schedule interface {
        //返回同一Entity中的job下一次执行的时间
        Next(time.Time) time.Time
    }
    
    type SpecSchedule struct {
        Second, Minute, Hour, Dom, Month, Dow uint64
    }
    
    type ConstantDelaySchedule struct {
        Delay time.Duration //循环时间间隔,最小单位为秒
    }
    
    //实例化Cron
    func New() *Cron {
        return &Cron{
            entries:  nil,
            add:      make(chan *Entry),
            stop:     make(chan struct{}),
            snapshot: make(chan []*Entry),
            running:  false,
        }
    }
    
    func Parse(spec string) (_ Schedule, err error)
    
    //将job加入Cron中,该方法只是简单的通过FuncJob类型强制转换cmd,然后调用AddJob方法
    func (c *Cron) AddFunc(spec string, cmd func()) error
    
    //将job加入Cron中,通过Parse函数解析cron表达式spec的到调度实例(Schedule),之后调用c.Schedule方法
    func (c *Cron) AddJob(spec string, cmd Job) error
    
    //获取当前Cron总所有Entities的快照
    func (c *Cron) Entries() []*Entry
    
    //通过两个参数实例化一个Entity,然后加入当前的Cron中,如果当前Cron未运行,则直接将该Entity加入Cron中
    //否则通过add这个成员channel将entity加入正在运行的Cron中
    func (c *Cron) Schedule(schedule Schedule, cmd Job)
    
    //新启动一个goroutine运行当前Cron
    func (c *Cron) Start()
    
    //通过给stop成员发送一个struct{}{}来停止当前的Cron,同时将running置为false,
    //从这里可以看出来stop只是去通知Cron停止,因此往channel发一个值即可,不用关心值的大小,
    //所以Cron中stop是一个空结构体
    func (c *Cron) Stop()

    4、示例:

    package main
    
    import (
        "log"
    
        "github.com/robfig/cron"
    )
    
    //linux中crontab只能精确到分钟,go中支持秒级别的
    func newWithSecond() *cron.Cron {
        secondParser := cron.NewParser(cron.Second | cron.Minute |
            cron.Hour | cron.Dom | cron.Month | cron.DowOptional | cron.Descriptor)
        return cron.New(cron.WithParser(secondParser), cron.WithChain())
    }
    
    type H struct {
        C *cron.Cron
    }
    
    func (h H) Run() {
        entries := h.C.Entries()
        if len(entries) > 0 {
            log.Println("---------cron running entries:", len(entries), ", next time:", entries[1].Next, ", pre time:", entries[1].Prev)
        }
    }
    
    func main() {
        i := 0
        c := newWithSecond()
        spec := "*/5 * * * * *"
        entryId, err := c.AddFunc(spec, func() {
            i++
            log.Println("cron running:", i)
            if i >= 1 {
                entries := c.Entries()
                log.Println("cron running entries:", len(entries), ", next time:", entries[0].Next, ", pre time:", entries[0].Prev)
            }
        })
        log.Println("entryId:", entryId, " err:", err)
    
        s, err := cron.ParseStandard("*/1 * * * * ")
        if err != nil {
            log.Println(err)
        }
    
        h := H{c}
        c.Schedule(s, h)
    
        c.Start()
        select {}
    }

     参考地址:https://www.jianshu.com/p/fd3dda663953http://www.luyixian.cn/news_show_232522.aspx

  • 相关阅读:
    p1373
    考试总结 2018-5-6
    p1044与p1898
    p1905
    p1904 p1903
    p1177
    p1273  日常打表
    p1142
    并查集与并查集模板
    p1265
  • 原文地址:https://www.cnblogs.com/ybf-yyj/p/12741339.html
Copyright © 2011-2022 走看看