我试图找到正确的方法来使用工人围棋例程产生的结果,同时在所有工作完成后优雅地退出结果循环。为了说明,我做了以下示例。我的真实世界案例与这个例子略有不同,因为我不知道每个工人围棋例程将返回多少“工作”,显然这些for循环执行固定数量的结果(5)。
我是goroutines和频道的新手,但以下是我所理解的基本租户;
范围
将继续,直到通道关闭package main
import (
"fmt"
"sync"
)
func worker1(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("1.%d", i)
}
wg.Done()
}
func worker2(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("2.%d", i)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
r := make(chan string)
wg.Add(2)
go worker1(r, &wg)
go worker2(r, &wg)
for i := range r {
fmt.Printf("Got job result: %s\n", i)
}
wg.Wait()
}
这个例子是死锁,因为范围循环永远不会退出,因为通道永远不会关闭。工作完成后,我可以在通道上执行关闭操作(即用close(r)
替换wg.done()
),但当另一个worker goroutine试图向已经关闭的通道发送进一步结果时,我会感到恐慌。
最后我想我可以移动wg了。Wait()
在结果循环上方,完成后关闭通道,然后开始打印结果,但这意味着在所有线程上的所有工作完成之前,我无法打印任何结果。
在所有工作线程完成后,如何正确地优雅地退出结果循环,同时也不要等到所有工作完成后才开始打印结果?
我已经编辑了你的代码,可以在没有死锁的情况下工作。问题是,通道上的接收阻塞了主线程,而您的两个goroutine
都没有发送更多数据。
此解决方案运行一个新的goroutine
,一旦WaitGroup
完成,它就会关闭结果通道。
package main
import (
"fmt"
"sync"
)
func worker1(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("1.%d", i)
}
wg.Done()
}
func worker2(r chan string, wg *sync.WaitGroup) {
for i := 0; i < 5; i++ {
r <- fmt.Sprintf("2.%d", i)
}
wg.Done()
}
func main() {
var wg sync.WaitGroup
r := make(chan string)
wg.Add(2)
go worker1(r, &wg)
go worker2(r, &wg)
go func() {
defer close(r)
wg.Wait()
}()
for i := range r {
fmt.Printf("Got job result: %s\n", i)
}
}
(去游乐场)
问题内容: 我正在Python中进行多处理实验,并试图在两个进程之间共享一个字符串数组。这是我的python代码: 运行脚本时,我看到该脚本已正确填充,并且可在中找到,但不能在中找到。结果如下: 我忽略了什么吗? 预先感谢您的反馈。:) 问题答案: 我的猜测是: 存储3个指针。将它们分配给当前进程之外没有意义的内存地址。尝试访问此时包含垃圾邮件的无意义地址。 分配对所有过程都有意义的值似乎有帮助:
有人能帮我吗?
我正在学习Spring Core认证,在提供的学习材料中,我对这个问题有一些疑问: 关闭应用程序上下文的首选方法是什么? 我知道如果我有这样的东西: 通过在上下文对象上使用close()方法,ApplicationContext被关闭,应用程序被销毁。 但我认为这不是我必须做的最好的方式。 阅读官方留档,我发现我也可以这样做: 在JVM中注册一个关闭挂钩,因此JVM将在JVM退出之前触发Sprin
问题内容: 我希望我的计时器一次执行一次actionPerformed方法(5秒一次),但是它多次在控制台“ Hello”中写入: 如何产生想要的效果?谢谢 问题答案: 如前所述,最好使用,但也可以在开始之前使用setRepeats():
问题内容: 我是Go菜鸟,无法找到在Go中打开mysql连接然后在http处理程序之间共享它的完整示例。到目前为止,这是我的代码,如何使用在HomeHandler中的main()中打开的db连接? 问题答案: 数据库/ sql程序包会自动为您管理连接池。 返回 代表连接池 而不是单个连接的句柄。如果池中的所有连接都忙,则数据库/ sql软件包会自动打开一个新连接。 将其应用于代码意味着,您只需要共