• 定时任务 cron


    cron表达式是我用过迄今为止最好用的定时器表达方式,比较的灵活,可以支持多种多样的灵活的定时器。

    先看最简单的用法:

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    
    func main() {
    	c := cron.New()
    	c.AddFunc("*/5 * * * * *", func() {
    		fmt.Println("每5秒执行一次")
    	})
    	c.Start()
    	select {}
    }
    

    如果业务比较复杂的话我们还可以进行更深一层次的封装。

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    func RunTimer(value string)  {
    	fmt.Println(value)
    	fmt.Println("每5秒执行一次")
    }
    func main() {
    	c := cron.New()
    	c.AddFunc("*/5 * * * * *", func() {
    		RunTimer("传入参数")
    	})
    	c.Start()
    	select {}
    }
    

    我们可以添加多条任务

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    func RunTimer(value string)  {
    	fmt.Println(value)
    	fmt.Println("每5秒执行一次")
    }
    func main() {
    	c := cron.New()
    	c.AddFunc("*/5 * * * * *", func() {
    		RunTimer("传入参数")
    	})
    	c.AddFunc("*/5 * * * * *", func() {
    		RunTimer("第二条任务传入参数")
    	})
    	c.Start()
    	select {}
    }
    

    还可以使用stop函数来停止我们的定时器

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    func RunTimer(value string)  {
    	fmt.Println(value)
    	fmt.Println("每5秒执行一次")
    }
    func main() {
    	c := cron.New()
    	c.AddFunc("*/5 * * * * *", func() {
    		RunTimer("传入参数")
    	})
    	c.AddFunc("*/5 * * * * *", func() {
    		RunTimer("第二条任务传入参数")
    	})
    	c.Start()
    	defer c.Stop()
    }
    

    除此之外还有一种job的方式,不过我认为这种方式用起来不是很直观,不推荐使用

     

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    
    type TestJob struct {
    
    }
    
    func (TestJob) Run()  {
    	fmt.Println("每5秒执行一次")
    }
    func main() {
    	c := cron.New()
    	c.AddJob("*/5 * * * * *",TestJob{})
    	c.Start()
    	defer c.Stop()
    }
    

    除了cron表达式它还有一种自己特定的写法

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    
    
    func main() {
    	c := cron.New()
    	c.AddFunc("@hourly", func() {
    		fmt.Println("每个小时执行一次")
    	})
    	c.Start()
    	defer c.Stop()
    }
    
    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    
    
    func main() {
    	c := cron.New()
    	c.AddFunc("@every 1h30m", func() {
    		fmt.Println("每个小时的第三十分钟执行")
    	})
    	c.Start()
    	defer c.Stop()
    }
    

    不过还是有一些需要注意的点,这个库的cron表达式和网上一些常规的cron表达式有点不同

     

     

    可以看到网上一些在线生成的表达式是有7位的

    我尝试把它放进去

    package main
    
    import (
    	"fmt"
    	"github.com/robfig/cron"
    )
    
    
    func main() {
    	c := cron.New()
    	err:=c.AddFunc("0/1 * * * * ? *", func() {
    		fmt.Println("每一秒执行一次")
    	})
    	if err!=nil{
    		fmt.Println(err.Error())
    	}
    	c.Start()
    	select {
    
    	}
    }
    

    执行结果报错了:

     

    查看了官方文档发现他缺少了年份这一位 所以这里不能使用常规的在线生成器生成的cron表达式去操作

     

    还有一点就是它不支持删除正在挂起的定时器任务

     

    于是我做了一个改装

     

    package main
    
    import (
    	"crypto/md5"
    	"encoding/hex"
    	"fmt"
    	"github.com/robfig/cron"
    	uuid "github.com/satori/go.uuid"
    )
    var CronArray=make(map[string]cron.Cron)
    
    func Get16MD5Encode(data string) string {
    	return GetMD5Encode(data)[8:24]
    }
    
    //获取uuid
    func GetUuid() string {
    	u := uuid.NewV4()
    	return Get16MD5Encode(u.String())
    }
    
    //返回一个32位md5加密后的字符串
    func GetMD5Encode(data string) string {
    	h := md5.New()
    	h.Write([]byte(data))
    	return hex.EncodeToString(h.Sum(nil))
    }
    
    func main() {
    	c := cron.New()
    	err:=c.AddFunc("0/1 * * * * ? *", func() {
    		fmt.Println("每一秒执行一次")
    	})
    	if err!=nil{
    		fmt.Println(err.Error())
    	}
    	c.Start()
    	cronId:=GetUuid()
    	CronArray[cronId]=*c
    	select {
    
    	}
    }
    

    如此一来我就可以通过map的key值传入来执行stop函数来停止掉指定的cron定时器任务

    但是这么写其实还是有风险的,当我们的程序异步竞争map时可能出现map为空的错误

    所以我们在改造一下

    package main
    
    import (
    	"crypto/md5"
    	"encoding/hex"
    	"fmt"
    	"github.com/robfig/cron"
    	uuid "github.com/satori/go.uuid"
    	"sync"
    )
    var CronArray sync.Map
    
    func Get16MD5Encode(data string) string {
    	return GetMD5Encode(data)[8:24]
    }
    
    //获取uuid
    func GetUuid() string {
    	u := uuid.NewV4()
    	return Get16MD5Encode(u.String())
    }
    
    //返回一个32位md5加密后的字符串
    func GetMD5Encode(data string) string {
    	h := md5.New()
    	h.Write([]byte(data))
    	return hex.EncodeToString(h.Sum(nil))
    }
    
    func main() {
    	c := cron.New()
    	err:=c.AddFunc("0/1 * * * * ? *", func() {
    		fmt.Println("每一秒执行一次")
    	})
    	if err!=nil{
    		fmt.Println(err.Error())
    	}
    	c.Start()
    	cronId:=GetUuid()
    	//添加cron定时器
    	CronArray.Store(cronId,*c)
    	//获取指定cron定时器关闭
    	getCron,ok:=CronArray.Load(cronId)
    	if ok{
    		cronNew:=getCron.(cron.Cron)
    		cronNew.Stop()
    	}
    	select {
    
    	}
    }
    

    但是这就意味着我们每个cron只能添加一个addfunc或者addjob

    后面有时间会尝试一下把源码拿来二次改装

  • 相关阅读:
    JavaWeb学习(17):优化三层(加入接口和 DBUtil)
    [每日一题]:The Lazy Cow(silver)
    JavaWeb学习(16): 三层架构模式实现简单的学生管理系统(内含数据库)
    BZOJ3275Number——二分图最大权独立集
    BZOJ3438小M的作物——最小割
    BZOJ2127happiness——最小割
    BZOJ3894文理分科——最小割
    BZOJ2150部落战争——最小路径覆盖
    BZOJ4205卡牌配对——最大流+建图优化
    BZOJ4032[HEOI2015]最短不公共子串——序列自动机+后缀自动机+DP+贪心
  • 原文地址:https://www.cnblogs.com/yangxinpython/p/16329633.html
Copyright © 2020-2023  润新知