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

标签 go goroutine file-writing channels ticker

过去一天左右,我一直在努力解决一个问题,以找出创建 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()
}

Go Playground Demo

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

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

最佳答案

你的程序永远不会退出的原因是 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
        }
    }

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

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

最后,如果你想重组你的程序只使用一个代码,你可以启动一个额外的 goroutine,它监听代码和 quit。 channel ,然后开始 N每个 tick 上的子 goroutines。

关于go - 在 Go 中定期调用 N 个并发函数的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56587109/

相关文章:

go - 关闭 channel 与发送例如一个空结构?

c - 用C写入文件

c - 在读取文件、计算和写入另一个文件时使用结构

C:使用 do while 循环写入/读取文件

go - 如何在Go中使用多个空白标识符?

MySQL顺序插入很慢,而线程插入很快 - 为什么?

c - 去 1.5+ : Error - imports runtime: C source files not allowed when not using cgo or SWIG

go - 在不同的结构中声明多个* sync.Mutex变量

linux - 在fsync中使用mmap是否安全? (fsync将使mmap上的某些页面无效吗?)

go - 如何在 Go 中从 system-d 服务运行时修复环境变量不起作用