在过去的一天左右的时间里,我一直在努力解决一个问题,以找出创建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()行上。另外,每个并发函数调用都使用其自己的代码-我可以通过任何方式使用一个“主”代码来运行所有功能吗?
提前谢谢!这是我第一次真正研究Go中的并发性。
答案 0 :(得分:5)
您的程序永不退出的原因是Go语言的一个奇怪现象:break
的{{1}}语句退出了case <-quit
语句,而不是循环。 (不确定为什么这种行为会有用。)要修复程序,您需要明确中断循环:
select
在编写代码时,它总是等到下一个滴答声才退出。您也可以通过在select语句中阅读tickLoop:
for a := range tick.C {
select {
case <-quit:
break tickLoop
default:
fmt.Println(a, "function #", id) // do something on tick
}
}
来解决此问题:
tick.C
最后,如果您想重组程序以仅使用一个代码,则可以启动一个额外的goroutine,该例程在代码和tickLoop:
for {
select {
case <-quit:
break tickLoop
case a := <-tick.C:
fmt.Println(a, "function #", id) // do something on tick
}
}
频道上侦听,然后启动quit
子菜单,每一个滴答声就会出现goroutines。