应用场景
电池船数据上报频次:航行中 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 结束
}