調度單個cron
- 這寫代碼的老師都喜歡用var 聲明變量后使用
- 下次調度時間: nextTime = expr.Next(now)
- 超時時間計算:nextTime.Sub(now)
- 超時后執行回調函數:time.AfterFunc
// 【github.com/gorhill/cronexpr】 這個包功能對應Linux的定時任務;但是這個包支持到秒級
/*
秒---> 0-59
分---> 0-59
時---> 0-23 0表示0點
日---> 1-31
月---> 1-12
周---> 0-6 0表示周日
年---> 1-12
*/
package main
import (
"fmt"
"time"
"github.com/gorhill/cronexpr"
)
func main() {
var (
err error
expr *cronexpr.Expression
now time.Time // 當前時間
nextTime time.Time // 下次調度時間
)
// 每5s執行一次
if expr, err = cronexpr.Parse("*/5 * * * * * *"); err != nil {
fmt.Println(err)
return
}
// 當前時間
now = time.Now()
// 下次調度時間 [時間規律是0,6,12,18,...,58],而不是根據啟動時間計算的
nextTime = expr.Next(now)
// 等待這定時器超時
// 超時時間計算:nextTime.Sub(now)
time.AfterFunc(nextTime.Sub(now), func() {
// 超時就會執行這回調函數
fmt.Println("被調度了", nextTime)
})
time.Sleep(6 * time.Second)
}
調度多個cron任務
package main
import (
"fmt"
"time"
"github.com/gorhill/cronexpr"
)
// 任務結構體--封裝
type CronJob struct {
expr *cronexpr.Expression // 時間表達式
nextTime time.Time // 下次調度時間
}
// 聲明一些全局變量
var (
cronJob *CronJob // job名字
expr *cronexpr.Expression // 時間表達式
now time.Time // 當前時間
scheduleTable map[string]*CronJob //key:任務名字, 調度表 存放所有定時任務
)
func main() {
// 需要有一個調度協程,讓他定時檢測所有的Corn任務,誰過期了就執行誰
// 當前時間
now = time.Now()
// 創建內存,map不可以直接使用,這里不給分配內存
scheduleTable = make(map[string]*CronJob)
// 定義兩個cornjob: 每5s執行一次; 每57執行一次
expr = cronexpr.MustParse("*/5 * * * * * *")
// 將調度器CronJob初始化且賦值給cronJob
cronJob = &CronJob{
expr: expr,
nextTime: expr.Next(now),
}
// 任務注冊到調度表
scheduleTable["job1"] = cronJob
// 定義兩個cornjob: 每5s執行一次; 每57執行一次
expr = cronexpr.MustParse("*/5 * * * * * *")
// 將調度器CronJob初始化且賦值給cronJob
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)
}
}
// 睡眠100 毫秒(不讓它占用過多cpu)
select {
case <-time.NewTimer(100 * time.Millisecond).C: //將在100 毫秒可讀,返回
}
// 簡單的 time.Sleep(100 *time.Second)
}
}()
time.Sleep(100 * time.Second)
}
# 實際效果
job1 下次執行時間是: 2022-03-15 00:54:45 +0800 CST
執行: job1
job2 下次執行時間是: 2022-03-15 00:54:45 +0800 CST
執行: job2
執行: job1
job1 下次執行時間是: 2022-03-15 00:54:50 +0800 CST
job2 下次執行時間是: 2022-03-15 00:54:50 +0800 CST
執行: job2
job1 下次執行時間是: 2022-03-15 00:54:55 +0800 CST
job2 下次執行時間是: 2022-03-15 00:54:55 +0800 CST
執行: job1
執行: job2
執行: job1
job1 下次執行時間是: 2022-03-15 00:55:00 +0800 CST
執行: job2
job2 下次執行時間是: 2022-03-15 00:55:00 +0800 CST
執行: job1
job1 下次執行時間是: 2022-03-15 00:55:05 +0800 CST
job2 下次執行時間是: 2022-03-15 00:55:05 +0800 CST