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

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

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


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()

}

Go Playground 演示

所以这个解决方案有效,以适当的时间间隔同时执行所有的代码并在 10 秒后完成,但它实际上并没有退出程序,而是挂在最后的 wg.Wait() 行上。此外,每个并发函数调用都使用自己的代码 - 有什么方法可以让所有函数都可以使用一个&ldquo;主&rdquo;代码?

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


拉风的咖菲猫
浏览 104回答 1
1回答

波斯汪

你的程序永远不会退出的原因是 Go 语言的一个奇怪的怪癖:breakfor 语句case <-quit退出select语句,而不是循环。(不知道为什么这种行为会有用。)要修复你的程序,你需要显式地打破循环:tickLoop:&nbsp; &nbsp; for a := range tick.C {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break tickLoop&nbsp; &nbsp; &nbsp; &nbsp; default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(a, "function #", id) // do something on tick&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }在编写代码时,它总是等到下一个时钟周期才退出。tick.C您也可以通过读取 select 语句来解决此问题:tickLoop:&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-quit:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break tickLoop&nbsp; &nbsp; &nbsp; &nbsp; case a := <-tick.C:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(a, "function #", id) // do something on tick&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }最后,如果您想重组程序以仅使用一个股票代码,您可以启动一个额外的 goroutine,它监听股票代码和通道quit,然后N在每个股票代码时启动子 goroutine。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go