带有 Ticker 的 Goroutine 选择循环导致 CPU 为 100%

Abi*_*yen 1 cpu cpu-usage go ticker goroutine

我有这个循环,它的作用是试图重复轮询另一台服务器。我使用 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
    }()
}
Run Code Online (Sandbox Code Playgroud)

然而,当监控循环开始时,每次发送到股票频道的信号时,CPU 都会持续显示 100%。

在 goroutine 中使用 Ticker 以便它不会消耗 100% CPU 时我错过了什么?

icz*_*cza 11

你的循环中select有一个default分支。如果其他cases 都没有准备好继续,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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)