在Go中定期调用N个并发函数的最佳方法是什么?

Nat*_*ela 4 go ticker file-writing goroutine channels

在过去一天左右的时间里,我一直在努力解决问题,以找出创建N个并发函数的最佳方法,这些函数在Go中以相同的时间间隔定期调用。我希望能够指定任意数量的功能,让它们全部同时定期运行,并在指定的时间后结束它们。

现在,我有一个可行的解决方案,但是必须为每个并发函数创建一个新的代码。我也不确定如何正确使用sync.WaitGroup,因为我当前的实现导致程序永无休止(只是卡在了wg.Wait()的最后)

我简要地看了一下名为Multitick的自动报价包装器,但不确定如何实现它。也许Multitick可能是这里的解决方案?

func main() {
    N := 10

    var wg sync.WaitGroup
    wg.Add(N)

    quit := make(chan struct{})

    for i := 0; i < N; i++ {

        tick := time.NewTicker(500 * time.Millisecond)
        go func(t *time.Ticker) {

            for a := range tick.C {

                select {
                case <-quit:
                    break
                default:
                    fmt.Println(a) // do something on tick
                }
            }
            wg.Done()
        }(tick)
    }

    time.Sleep(10 * time.Second)
    close(quit)
    wg.Wait()
}
Run Code Online (Sandbox Code Playgroud)

前往游乐场示范

因此,此解决方案有效,可以以适当的间隔同时执行所有代码,并在10秒后完成,但实际上并没有退出程序,最终挂在wg.Wait()行上。另外,每个并发函数调用都使用自己的代码-我可以通过任何方式使用一个“主”代码来运行所有函数吗?

提前致谢!这是我第一次真正研究Go的并发性。

joc*_*hen 5

您的程序永不退出的原因是Go语言的一个奇怪现象:break语句case <-quit退出select而不是循环。(不确定为什么这种行为会有用。)要修复程序,您需要显式中断循环:

tickLoop:
    for a := range tick.C {
        select {
        case <-quit:
            break tickLoop
        default:
            fmt.Println(a, "function #", id) // do something on tick
        }
    }
Run Code Online (Sandbox Code Playgroud)

在编写代码时,它总是等到下一个滴答声才退出。您也可以通过阅读tick.Cselect语句来解决此问题:

tickLoop:
    for {
        select {
        case <-quit:
            break tickLoop
        case a := <-tick.C:
            fmt.Println(a, "function #", id) // do something on tick
        }
    }
Run Code Online (Sandbox Code Playgroud)

最后,如果要重组程序以仅使用一个代码,则可以启动一个额外的goroutine,该例程在代码和quit通道上侦听,然后N在每个代码上启动子goroutine。