golang 定时器的不同任务
应用场景
电池船数据上报频次:航行中 1次/30秒,不航行 1次/1小时
电池簇数据上报频次:工作中 1次/1秒,不工作 不上报
main.go
package main import ( "fmt" "os" "os/signal" "syscall" "ticker/util" "time" ) var ticker1 *util.DynamicTicker var ticker2 *util.DynamicTicker func report_batteryship() { // 航行时1秒/次,不航行时10秒/次 fmt.Println("report_batteryship:", time.Now()) } func report_batterycluster() { // 工作时1秒/次,不工作时不上报 fmt.Println("report_batterycluster:", time.Now()) } func main() { sleeptime := 10 * time.Second // ticker1 = util.NewDynamicTicker(1*time.Second, report_batteryship) // ticker1.SetWorkStatus(true) // go func() { // fmt.Println("航行中") // time.Sleep(sleeptime) // fmt.Println("不航行") // ticker1.ChangeInterval(10 * time.Second) // time.Sleep(sleeptime * 6) // fmt.Println("航行中") // ticker1.ChangeInterval(1 * time.Second) // }() ticker2 = util.NewDynamicTicker(2*time.Second, report_batterycluster) ticker2.SetWorkStatus(true) go func() { fmt.Println("开始工作") time.Sleep(sleeptime) fmt.Println("停止工作") ticker2.SetWorkStatus(false) time.Sleep(sleeptime) fmt.Println("开始工作") ticker2.SetWorkStatus(true) }() // 监听操作系统信号,阻塞直到接收到信号 quit := make(chan os.Signal, 1) signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) <-quit }
ticker.go
package util import ( "sync" "time" ) // 是一个可以动态改变时间间隔的定时器 type DynamicTicker struct { currentTicker *time.Ticker // 当前正在使用的 ticker nextTicker *time.Ticker // 下一个要切换到的 ticker work bool // 工作状态标志 quit chan struct{} // 用于停止 goroutine 的信号通道 mu sync.Mutex // 互斥锁,用于保护并发访问 worker func() // 定时执行的工作函数 wg sync.WaitGroup // 等待组,用于等待 goroutine 结束 } // 创建一个新的 DynamicTicker 实例 func NewDynamicTicker(interval time.Duration, worker func()) *DynamicTicker { dt := &DynamicTicker{ currentTicker: time.NewTicker(interval), // 初始化当前 ticker quit: make(chan struct{}), // 初始化停止信号通道 worker: worker, // 设置工作函数 } dt.wg.Add(1) // 增加等待组的计数器 go dt.run() // 启动 goroutine 执行 run 方法 return dt } // 监听信号 func (dt *DynamicTicker) run() { defer dt.wg.Done() // 在 goroutine 结束时减少等待组的计数器 for { select { case <-dt.currentTicker.C: // 接收到当前 ticker 的信号 dt.mu.Lock() if dt.work { // 如果处于工作状态 dt.worker() // 执行工作函数 } // 如果存在下一个 ticker,则切换到下一个 ticker if dt.nextTicker != nil { dt.currentTicker.Stop() // 停止当前 ticker dt.currentTicker = dt.nextTicker // 切换到下一个 ticker dt.nextTicker = nil // 重置下一个 ticker } dt.mu.Unlock() case <-dt.quit: // 接收到停止信号 dt.currentTicker.Stop() // 停止当前 ticker if dt.nextTicker != nil { // 如果存在下一个 ticker,也停止它 dt.nextTicker.Stop() } return // 退出 goroutine } } } // 动态改变定时器的间隔 func (dt *DynamicTicker) ChangeInterval(newInterval time.Duration) { dt.mu.Lock() defer dt.mu.Unlock() dt.nextTicker = time.NewTicker(newInterval) // 创建新的 ticker 作为下一个 ticker } // 设置定时器的工作状态 func (dt *DynamicTicker) SetWorkStatus(work bool) { dt.mu.Lock() defer dt.mu.Unlock() dt.work = work // 更新工作状态 } // 停止定时器 func (dt *DynamicTicker) Stop() { close(dt.quit) // 关闭停止信号通道 dt.wg.Wait() // 等待 goroutine 结束 }
qq:505645074