golang實現定時任務調度


調度單個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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM