基于time包封装定时器
package cron
import (
"context"
"runtime/debug"
"sync"
"time"
)
type Timer struct {
ctx context.Context
cancel context.CancelFunc
timer *time.Timer
process func()
mu sync.Mutex
concurrency int
sem chan struct{}
startHour int
endHour int
enabled bool
duration time.Duration
}
func NewTimer(duration time.Duration, process func(), concurrent, startHour, endHour int) *Timer {
ctx, cancel := context.WithCancel(context.Background())
timer := time.NewTimer(duration)
return &Timer{
ctx: ctx,
cancel: cancel,
timer: timer,
process: process,
concurrency: concurrent,
sem: make(chan struct{}, concurrent),
startHour: startHour,
endHour: endHour,
enabled: true,
duration: duration,
}
}
func (t *Timer) shouldProcess() bool {
now := time.Now().Hour()
return now >= t.startHour && now <= t.endHour
}
func (t *Timer) Start() {
if t.ctx.Err() != nil {
return
}
for {
select {
case <-t.timer.C:
t.timer.Reset(t.duration)
t.processIfEnabled()
case <-t.ctx.Done():
return
}
}
}
func (t *Timer) processIfEnabled() {
t.mu.Lock()
defer t.mu.Unlock()
if t.process != nil && t.shouldProcess() && t.enabled {
t.sem <- struct{}{}
go func() {
defer func() {
<-t.sem
t.ThrowException()
}()
t.process()
}()
}
}
func (t *Timer) Enable() {
t.mu.Lock()
defer t.mu.Unlock()
t.enabled = true
}
func (t *Timer) Disable() {
t.mu.Lock()
defer t.mu.Unlock()
t.enabled = false
}
func (t *Timer) Stop() {
t.timer.Stop()
t.cancel()
}
func (t *Timer) ThrowException() {
if r := recover(); r != nil {
debug.PrintStack()
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接