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 结束
}
相关推荐
Wenweno0o15 分钟前
Eino - 错误处理与稳定性
golang·智能体·eino
天若有情67316 分钟前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
好家伙VCC20 分钟前
**发散创新:基于Python与ROS的机器人运动控制实战解析**在现代机器人系统开发中,**运动控制**是实现智能行为的核心
java·开发语言·python·机器人
2401_8274999920 分钟前
python项目实战09-AI智能伴侣(ai_partner_2-3)
开发语言·python
派葛穆23 分钟前
汇川PLC-Python与汇川easy521plc进行Modbustcp通讯
开发语言·python
lzhdim1 小时前
SharpCompress:跨平台的 C# 压缩与解压库
开发语言·c#
嘿嘿嘿x31 小时前
Linux记录过程
linux·开发语言
默 语1 小时前
Records、Sealed Classes这些新特性:Java真的变简单了吗?
java·开发语言·python
止观止1 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
王码码20351 小时前
Go语言中的Elasticsearch操作:olivere实战
后端·golang·go·接口