timerroutine.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // 定时协程
  2. // 定时或发通知调用协程函数
  3. package coroutine
  4. import (
  5. "context"
  6. "leafstalk/log"
  7. "sync"
  8. "time"
  9. )
  10. // TimerRoutine 定时协程类
  11. type TimerRoutine struct {
  12. name string
  13. interval time.Duration
  14. chEvent chan struct{}
  15. wg sync.WaitGroup
  16. cancel context.CancelFunc
  17. taskFunc func() // 定时执行的任务函数
  18. }
  19. // NewTimerRoutine 创建一个定时协程实例
  20. func NewTimerRoutine(name string, interval time.Duration, taskFunc func()) *TimerRoutine {
  21. return &TimerRoutine{
  22. name: name,
  23. interval: interval,
  24. chEvent: make(chan struct{}, 1),
  25. taskFunc: taskFunc,
  26. }
  27. }
  28. // Start 启动定时协程
  29. func (tr *TimerRoutine) Start() {
  30. ctx, cancel := context.WithCancel(context.Background())
  31. tr.cancel = cancel
  32. tr.wg.Add(1)
  33. go func() {
  34. defer func() {
  35. tr.wg.Done()
  36. log.Infof("TimerRoutine.Start exit %s", tr.name)
  37. }()
  38. tr.run(ctx)
  39. }()
  40. }
  41. // Stop 停止定时协程,等待协程退出
  42. func (tr *TimerRoutine) Stop() {
  43. tr.cancel()
  44. tr.wg.Wait()
  45. }
  46. // Notify 发送事件通知,触发任务执行
  47. func (tr *TimerRoutine) Notify() {
  48. select {
  49. case tr.chEvent <- struct{}{}:
  50. default:
  51. }
  52. }
  53. // run 定时协程的核心逻辑
  54. func (tr *TimerRoutine) run(ctx context.Context) {
  55. ticker := time.NewTicker(tr.interval)
  56. defer func() {
  57. ticker.Stop()
  58. log.Infof("TimerRoutine.run exit %s", tr.name)
  59. }()
  60. safeDo := func() {
  61. defer func() {
  62. if err := recover(); err != nil {
  63. // 处理 panic,例如记录日志
  64. log.Infof("TimerRoutine recover panic %s: %v", tr.name, err)
  65. }
  66. }()
  67. tr.taskFunc()
  68. }
  69. for {
  70. select {
  71. case <-ctx.Done():
  72. return
  73. case <-ticker.C:
  74. case <-tr.chEvent:
  75. }
  76. if tr.taskFunc != nil {
  77. safeDo()
  78. }
  79. }
  80. }
  81. func example1() {
  82. timerRoutine := NewTimerRoutine("MyTimer", time.Second*5, func() {
  83. })
  84. timerRoutine.Start()
  85. timerRoutine.Stop()
  86. }