gtimer是一个并发安全的高性能任务定时器,类似于JavaTimergtimer组件旧版本采用的是分层时间轮(Hierarchical Timing Wheel)设计,从goframe v1.16版本开始,采用了优先级队列(PriorityQueue)实现。

使用场景

任何定时任务场景,大批量定时任务/延迟任务的场景,超时控制/频率控制的业务场景,对于定时时间准确度要求不高的业务场景。

注意事项

  1. 任何的定时任务都是有误差的,在定时间隔比较大,或者并发量大,负载较高的系统中尤其明显,具体请参考:https://github.com/golang/go/issues/14410
  2. 定时间隔不会考虑任务的执行时间。例如,如果一项工作需要3分钟才能执行完成,并且计划每隔5分钟运行一次,那么每次任务之间只有2分钟的空闲时间。
  3. 需要注意的是单例模式运行的定时任务,任务的执行时间会影响该任务下一次执行的开始时间。例如:一个每间隔1秒执行的任务,运行耗时为1秒,那么在第1秒开始运行后,下一次任务将会在第3秒开始执行。因为中间有一次运行检查时发现有当前任务正在进行,因此退出等待下一次执行检查。

使用方式:

  1. import "github.com/gogf/gf/os/gtimer"

接口文档

https://godoc.org/github.com/gogf/gf/os/gtimer

简要说明:

  1. New方法用于创建自定义的任务定时器对象,并可在创建时通过intervalTimerOptions参数指定定时器的最小tick时间间隔。
  2. Add方法用于添加定时任务,其中:
    • interval 参数用于指定方法的执行的时间间隔。
    • job 参数为需要执行的任务方法。
  3. AddEntry方法添加定时任务,支持更多参数的控制。
  4. AddSingleton方法用于添加单例定时任务,即同时只能有一个该任务正在运行。
  5. AddOnce方法用于添加只运行一次的定时任务,当运行一次数后该定时任务自动销毁。
  6. AddTimes方法用于添加运行指定次数的定时任务,当运行times次数后该定时任务自动销毁。
  7. Search方法用于根据名称进行定时任务搜索(返回定时任务*Entry对象指针)。
  8. Start方法用于启动定时器(使用New创建定时器时会自动启动)。
  9. Stop方法用于停止定时器。
  10. Close方法用于关闭定时器。

默认定时器

大部分的场景下使用默认的定时器即可。使用gtimer的默认定时器时,默认的间隔时间为100ms,因此理论的时间间隔误差范围为0~100ms。可以使用以下两种方式修改默认的定时器参数:

  1. 使用启动参数
    • gf.gtimer.interval=50: 修改默认的时间刻度为50毫秒
  2. 使用环境变量
    • GF_GTIMER_INTERVAL=50

性能测试

  1. goos: linux
  2. goarch: amd64
  3. pkg: github.com/gogf/gf/os/gtimer
  4. Benchmark_Add-12 4048776 291.9 ns/op 249 B/op 6 allocs/op
  5. Benchmark_StartStop-12 100000000 10.96 ns/op 0 B/op 0 allocs/op
  6. PASS
  7. ok command-line-arguments 6.602s

使用示例

基本示例

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/os/gtime"
  5. "github.com/gogf/gf/os/gtimer"
  6. "time"
  7. )
  8. func main() {
  9. now := time.Now()
  10. gtimer.AddTimes(time.Second, 10, func() {
  11. fmt.Println(gtime.Now(), time.Duration(time.Now().UnixNano()-now.UnixNano()))
  12. now = time.Now()
  13. })
  14. select {}
  15. }

执行后,输出结果为:

  1. 2021-05-27 13:28:19 1.004516s
  2. 2021-05-27 13:28:20 997.262ms
  3. 2021-05-27 13:28:21 999.972ms
  4. 2021-05-27 13:28:22 1.00112s
  5. 2021-05-27 13:28:23 998.773ms
  6. 2021-05-27 13:28:24 999.957ms
  7. 2021-05-27 13:28:25 1.002468s
  8. 2021-05-27 13:28:26 997.468ms
  9. 2021-05-27 13:28:27 999.981ms
  10. 2021-05-27 13:28:28 1.002504s

单例任务

  1. package main
  2. import (
  3. "github.com/gogf/gf/os/glog"
  4. "github.com/gogf/gf/os/gtimer"
  5. "time"
  6. )
  7. func main() {
  8. interval := time.Second
  9. gtimer.AddSingleton(interval, func() {
  10. glog.Println("doing")
  11. time.Sleep(5*time.Second)
  12. })
  13. select { }
  14. }

执行后,输出结果为:

  1. 2019-01-23 17:04:18.892 doing
  2. 2019-01-23 17:04:24.890 doing
  3. 2019-01-23 17:04:29.892 doing
  4. 2019-01-23 17:04:35.891 doing
  5. ...

延迟任务

延迟任务是指在指定时间后生效的定时任务。我们可以通过DelayAdd*相关方法实现延迟任务的创建。

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/os/gtime"
  5. "github.com/gogf/gf/os/gtimer"
  6. "time"
  7. )
  8. func main() {
  9. fmt.Println("Start:", gtime.Now())
  10. gtimer.DelayAdd(time.Second, time.Second, func() {
  11. fmt.Println("Running:", gtime.Now())
  12. })
  13. select {}
  14. }

执行后,终端输出:

  1. Start: 2021-05-27 13:26:02
  2. Running: 2021-05-27 13:26:04
  3. Running: 2021-05-27 13:26:05
  4. Running: 2021-05-27 13:26:06
  5. Running: 2021-05-27 13:26:07
  6. Running: 2021-05-27 13:26:08
  7. Running: 2021-05-27 13:26:09
  8. Running: 2021-05-27 13:26:10
  9. Running: 2021-05-27 13:26:11
  10. ...

SetTimeoutSetInterval

这两个方法来源于Javascript常用定时方法。其中SetTimeout用于创建只执行一次的定时任务,不过可以通过递归调用SetTimeout来实现无限间隔执行。SetIterval用于创建间隔执行不退出的定时任务。

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/os/gtime"
  5. "github.com/gogf/gf/os/gtimer"
  6. "time"
  7. )
  8. func main() {
  9. gtimer.SetTimeout(time.Second, func() {
  10. fmt.Println("SetTimeout:", gtime.Now())
  11. })
  12. gtimer.SetInterval(time.Second, func() {
  13. fmt.Println("SetInterval:", gtime.Now())
  14. })
  15. select {}
  16. }

执行后,终端输出:

  1. SetInterval: 2021-05-27 13:20:50
  2. SetTimeout: 2021-05-27 13:20:50
  3. SetInterval: 2021-05-27 13:20:51
  4. SetInterval: 2021-05-27 13:20:52
  5. SetInterval: 2021-05-27 13:20:53
  6. SetInterval: 2021-05-27 13:20:54
  7. SetInterval: 2021-05-27 13:20:55
  8. SetInterval: 2021-05-27 13:20:56
  9. SetInterval: 2021-05-27 13:20:57
  10. SetInterval: 2021-05-27 13:20:58
  11. ...

Exit退出

我们可以在定时任务中通过Exit方法强制退出定时任务的继续执行,该定时任务将会被从定时器中移除。

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/gogf/gf/os/gtime"
  5. "github.com/gogf/gf/os/gtimer"
  6. "time"
  7. )
  8. func main() {
  9. gtimer.SetInterval(time.Second, func() {
  10. fmt.Println("exit:", gtime.Now())
  11. gtimer.Exit()
  12. })
  13. select {}
  14. }

执行后,终端输出:

  1. exit: 2021-05-27 13:31:24

gtimergcron区别

gtimer任务定时器与gcron定时任务模块区别:

  • gtimer属于高性能模块,是框架核心模块,构建任何定时任务的基础,任何方法操作耗时均在纳秒级别。
  • gtimer可适用于任何的定时任务场景中,例如: TCP通信、游戏开发等场景。
  • gcron支持经典的crontab形式的定时任务语法,最小时间设定间隔为
  • gcron底层实现基于gtimer

Content Menu