2

是否可以使用 Ticker 实现长时间运行的守护进程的优雅终止?我在这里阅读了另一个相关线程,您应该始终关闭通道以避免内存泄漏,但是如果我在守护程序模式下运行它(假设我使用daemonize来处理 golang 之外的守护程序操作),真的没有办法让它在进程终止之前进行任何集体清理。除非我遗漏了什么,否则我在这里询问是否有替代/更好的方法在 Golang 中执行此操作

func main() {
  ticker := time.NewTicker(Interval)
  workers := make(chan bool, 1)

  for t := range ticker.C {
    select {
      case <- ticker.C:
        log.Println("Scheduled task is triggered.", t)
        go runWorker(workers)
      case <- workers:
        log.Println("Scheduled task is completed.")
        // can't return, it needs to be continue running
    }
  }
}
4

2 回答 2

3

我不确定我是否完全理解您的目标,但是您始终可以使用signal.Notify

func main() {
    ticker := time.NewTicker(Interval)
    workers := make(chan bool, 1)
    death := make(chan os.Signal, 1)
    signal.Notify(death, os.Interrupt, os.Kill)

    for {
        select {
        case <-ticker.C:
            log.Println("Scheduled task is triggered.", t)
            go runWorker(workers)
        case <-workers:
            log.Println("Scheduled task is completed.")
            // can't return, it needs to be continue running
        case <- death:
            //do any clean up you need and return
        }
    }
}
于 2014-08-02T02:44:05.873 回答
1

您的 main 函数两次读取代码通道,一次在一个滴答之后,然后在另一个滴答之后再次读取,然后再继续,这可能不是您想要的(如果 Interval 是 30 分钟,那么您只会每 60 分钟运行一次 goroutine)。这将是一个更好的方法:

func main() {
  ticker := time.NewTicker(Interval)
  workers := make(chan bool, 1)

  for {
    select {
      case <- ticker.C:
        log.Println("Scheduled task is triggered.", t)
        go runWorker(workers)
      case <- workers:
        log.Println("Scheduled task is completed.")
        // can't return, it needs to be continue running
    }
  }
}

这将在每个间隔之后继续创建一个 goroutine。在循环完成之前,您无需关闭此通道。如果您的应用程序刚刚退出,那么您的频道将被安全清理。如果您需要提前停止循环,请确保在退出循环之前调用ticker.Stop()。

如果您只想在间隔后运行一次 goroutine,请使用time.AfterFunc

于 2014-08-05T16:35:51.377 回答