带有 Ticker 的 Goroutine select 循环导致 CPU 到 100%

Goroutine select loop with Ticker causes CPU to 100%

我有一个循环,它所做的是尝试重复轮询到另一台服务器。我使用 ticker 来实现此目的,但该程序反复显示 100% CPU 使用率。

此自动收报机在 goroutine 中运行。并且 HTTP 服务器在另一个 goroutine 中运行。


func() Monitor() {

  abort := make(chan bool)

  log.Info("Monitor started.")

  // start the monitor goroutine
  go func() {
      defer log.Info("Stopped monitor")
        
      ticker := time.NewTicker(time.Duration(35.0) * time.Second)
      defer ticker.Stop()
        
      log.Info("Monitor started! \n")
      for {
        select {
        case t := <-ticker.C:
            log.Infof("Subscribe to service at time %v\n", t)
            if err := selfConn.SubscribeToService(); err != nil {
                log.Errorf("Failed to subscribe to primary connector: %v", err)
            } 
        case <-abort:
            log.Info("Finished routine!")
            return
        default:
            continue
        }
        }
    }() 
  
    go func() {
        time.Sleep(10 * time.Minute)
        abort <- true
    }()
}

然而,当监控循环开始时,每次向行情通道发送信号时,CPU 持续显示 100%。

我在 goroutine 中使用 ticker 使其不会消耗 100% 时错过了什么CPU?

你有一个 select 和一个 default 循环内的分支。如果其他 case 中的 none 准备好继续,default 分支会立即执行,因此您的下一次迭代会立即开始而无需等待。这是一个繁忙的循环。

此外,不需要另一个 goroutine 终止,您可以在同一个 goroutine 中为此使用计时器。

例如:

func monitor() {
    log.Info("Monitor started.")

    ticker := time.NewTicker(35 * time.Second)
    defer ticker.Stop()

    timeoutCh := time.After(10 * time.Minute)
    for {
        select {
        case t := <-ticker.C:
            log.Infof("Subscribe to service at time %v\n", t)
            if err := selfConn.SubscribeToService(); err != nil {
                log.Errorf("Failed to subscribe to primary connector: %v", err)
            }
        case <-timeoutCh:
            log.Info("Finished routine!")
            return
        }
    }
}