是否有更好的替代方法来使用围棋中的睡眠程序?

问题描述 投票:0回答:1

我想写一个worker,它每隔1个小时做一次工作。目前我们的系统中还没有cron,所以不想增加cron。请求在后续的实现中提出建议。

func init(){
     go startWorker()
}

func startWorker(){
     doJob()
     time.Sleep(time.Second * 3600)
}

在go例程中使用sleep是个坏主意吗? 或者有什么更好的选择来做这些事情?doJob() 是为了从DB中获取过去一小时内发生的所有故障,并进行重试。

go sleep goroutine thread-sleep
1个回答
2
投票

有两个问题,在使用 time.Sleep 以你设想的方式,一主一辅。

你没有办法终止这条规程。

goroutine被卡在一个无限循环中,所以除非 doJob 恐慌,它永远不会终止。 你可能应该给它传递一个通道,当goroutine需要终止时,这个通道将被关闭。

done := make(chan struct{})
go worker(done)
...
close(done)
...
func worker(done <-chan struct{}){
    for {
        doJob()
        timer := time.NewTimer(time.Hour)
        select {
        case <-timer.C:
            // nothing
        case <-done:
            timer.Stop()
            return
        }
    }
}

或者,更好的是,使用ticker:

func worker(done <-chan struct{}){
    ticker := time.NewTicker(time.Hour)
    for {
        doJob()
        select {
        case <-ticker.C:
            // nothing
        case <-done:
           ticker.Stop
           return
        }
    }
}

在这里,使用 defer:

func worker(done <-chan struct{}){
    ticker := time.NewTicker(time.Hour)
    defer ticker.Stop()
    for {
        doJob()
        select {
        case <-ticker.C:
            // nothing
        case <-done:
           return
        }
    }
}

你在浪费一叠钱

虽然goroutine使用的CPU资源可以忽略不计,但它却使用了一个堆栈,大约有十几千字节。 这对你来说可能不是一个问题,但如果是这样,而且如果你的应用程序有一个主循环,那么你可以插入你的 ticker 和调用的 doWork 入主 select 主循环的语句。

© www.soinside.com 2019 - 2024. All rights reserved.