猿问

我们如何确定 Go 中“最后一个”工作进程/线程何时完成?

我将使用一个 hacky 低效的素数查找器来使这个问题更加具体。


假设我们的 main 函数触发了一堆“worker”goroutine。他们会将结果报告给打印它们的单个通道。但并不是每个工人都会报告一些事情,所以我们不能使用计数器来知道最后一个工作何时完成。或者有什么办法吗?


对于具体的例子,在这里,main 触发 goroutine 以检查值 2...1000 是否为素数(是的,我知道它效率低下)。


package main


import (

    "fmt"

    "time"

)


func main() {

    c := make(chan int)

    go func () {

        for {

            fmt.Print(" ", <- c)

        }

    }()

    for n := 2; n < 1000; n++ {

        go printIfPrime(n, c)

    }

    time.Sleep(2 * time.Second)   // <---- THIS FEELS WRONG

}


func printIfPrime(n int, channel chan int) {

    for d := 2; d * d <= n; d++ {

        if n % d == 0 {

            return

        }

    }

    channel <- n

}

我的问题是我不知道如何在正确的时间可靠地停止它。我尝试在末尾添加一个 sleepmain并且它可以工作(但它可能需要太长时间,而且这不是编写并发代码的方法!)。我想知道是否有办法通过通道或其他方式发送停止信号,以便main在正确的时间停止。


这里的诀窍是我不知道会有多少工人响应。


这是不可能的还是有一个很酷的技巧?


(如果这个主要示例有答案,那就太好了。我可能可以概括。或者可能没有。也许这是特定于应用程序的?)


一只甜甜圈
浏览 236回答 1
1回答

MMMHUHU

使用WaitGroup.以下代码使用两个 WaitGroup。main 函数用于wgTest等待print_if_prime函数完成。完成后,它会关闭通道以中断打印 goroutine 中的 for 循环。主要功能用于wgPrint等待打印完成。package mainimport (&nbsp; "fmt"&nbsp; "sync")&nbsp;func main() {&nbsp; c := make(chan int)&nbsp; var wgPrint, wgTest sync.WaitGroup&nbsp; wgPrint.Add(1)&nbsp; go func(wg *sync.WaitGroup) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; for n := range c {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Print(" ", n)&nbsp; &nbsp; }&nbsp; }(&wgPrint)&nbsp; for n := 2; n < 1000; n++ {&nbsp; &nbsp; wgTest.Add(1)&nbsp; &nbsp; go print_if_prime(&wgTest, n, c)&nbsp; }&nbsp; wgTest.Wait()&nbsp; close(c)&nbsp; wgPrint.Wait()}func print_if_prime(wg *sync.WaitGroup, n int, channel chan int) {&nbsp; defer wg.Done()&nbsp; for d := 2; d*d <= n; d++ {&nbsp; &nbsp; if n%d == 0 {&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; }&nbsp; channel <- n}
随时随地看视频慕课网APP

相关分类

Go
我要回答