在 Go 中定期调用 N 个并发函数的最佳方法是什么?
What is the best way to call N concurrent functions periodically in Go?
在过去一天左右的时间里,我一直在努力解决一个问题,以找出创建 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()
}
所以这个解决方案有效,以适当的时间间隔同时执行所有代码并在 10 秒后完成,但它实际上并没有退出程序,挂在 wg.Wait() 行结尾。此外,每个并发函数调用都使用自己的自动收报机 - 有什么办法可以让所有函数都从一个 "master" 自动收报机运行吗?
提前致谢!这是我第一次真正深入研究 Go 中的并发。
你的程序永远不会退出的原因是 Go 语言的一个奇怪的怪癖:case <-quit
的 break
语句退出 select
语句,而不是循环。 (不知道为什么这种行为会有用。)要修复你的程序,你需要明确地打破循环:
tickLoop:
for a := range tick.C {
select {
case <-quit:
break tickLoop
default:
fmt.Println(a, "function #", id) // do something on tick
}
}
在编写代码时,它总是等到下一个报价单才会退出。您也可以通过阅读 select 语句中的 tick.C
来解决此问题:
tickLoop:
for {
select {
case <-quit:
break tickLoop
case a := <-tick.C:
fmt.Println(a, "function #", id) // do something on tick
}
}
最后,如果你想重组你的程序只使用一个自动收报机,你可以启动一个额外的 goroutine,它监听自动收报机和 quit
频道,然后启动 N
sub-goroutines 每次报价。
在过去一天左右的时间里,我一直在努力解决一个问题,以找出创建 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()
}
所以这个解决方案有效,以适当的时间间隔同时执行所有代码并在 10 秒后完成,但它实际上并没有退出程序,挂在 wg.Wait() 行结尾。此外,每个并发函数调用都使用自己的自动收报机 - 有什么办法可以让所有函数都从一个 "master" 自动收报机运行吗?
提前致谢!这是我第一次真正深入研究 Go 中的并发。
你的程序永远不会退出的原因是 Go 语言的一个奇怪的怪癖:case <-quit
的 break
语句退出 select
语句,而不是循环。 (不知道为什么这种行为会有用。)要修复你的程序,你需要明确地打破循环:
tickLoop:
for a := range tick.C {
select {
case <-quit:
break tickLoop
default:
fmt.Println(a, "function #", id) // do something on tick
}
}
在编写代码时,它总是等到下一个报价单才会退出。您也可以通过阅读 select 语句中的 tick.C
来解决此问题:
tickLoop:
for {
select {
case <-quit:
break tickLoop
case a := <-tick.C:
fmt.Println(a, "function #", id) // do something on tick
}
}
最后,如果你想重组你的程序只使用一个自动收报机,你可以启动一个额外的 goroutine,它监听自动收报机和 quit
频道,然后启动 N
sub-goroutines 每次报价。