这里写了个定时任务调度的方案:由定时器去触发一个job,job的执行时间不定,需要有超时处理。
这里使用content中的withTimeout处理(与自己起个超时判断协程是一样的效果),主程等待协程的job执行,成功/超时都继续执行下次运行(当然也可以超时后关闭这个定时任务也是可以的)
这是个简单的定时小框架,其有可能可完善成一个完整的定时调度工具。
package main
import (
"context"
"fmt"
"math/rand"
"time"
)
func doJob(sig chan bool, timeout time.Duration) {
ctx, cancel := context.WithTimeout(context.Background(), timeout) //超时控制
defer cancel() //回调的方法入defer栈
done := make(chan bool)
go func(ctx context.Context) {
fmt.Printf("->%s Dooing the Job\n", time.Now().Format("2006-01-02 15:04:05"))
time.Sleep(time.Duration(rand.Intn(10)) * time.Second) //模拟一个随机执行时间的任务
fmt.Printf("<-%s Ending the Job\n\n", time.Now().Format("2006-01-02 15:04:05"))
done <- false
}(ctx)
select {
case <-done: //任务完成了
sig <- true
return
case <-ctx.Done(): //超时了
sig <- false
return
}
}
func doRunTicker(duration time.Duration, timeout time.Duration) {
sig := make(chan bool)
timer := time.NewTimer(duration)
for {
<-timer.C //等待定时器信号
go doJob(sig, timeout)
if x := <-sig; !x {
fmt.Printf("[E]%s 任务超时\n\n", time.Now().Format("2006-01-02 15:04:05"))
//return //关闭任务
}
timer.Reset(duration) //重置定时器,开始下次任务
}
}
func main() {
rand.Seed(time.Now().UnixNano())
doRunTicker(2*time.Second, 5*time.Second)
}