2016-05-12 54 views
0

我會用一個黑客無效的素數查找器來使這個問題更具體。我們如何確定Go中「最後」工作進程/線程何時完成?

讓我們假設我們的主要功能引發了一堆「工作人員」goroutines。他們會將結果報告給打印它們的單個通道。但是並非每個員工都會報告,所以我們不能使用計數器來知道上一份工作何時完成。還是有辦法?

對於具體的例子,在這裏,主要關閉goroutines來檢查值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 
} 

我的問題是,我不知道如何在合適的時間可靠地停止它。我嘗試在main的末尾添加一個睡眠並且它可以工作(但它可能需要很長時間,而這不是編寫併發代碼的方法!)。我想知道是否有辦法通過某個頻道發送停止信號或其他東西,因此main可以在正確的時間停止。

這裏的訣竅是,我不知道會有多少員工回覆。

這是不可能的還是有一個很酷的把戲?

(如果有這個典型的例子一個答案,太棒了。我也許可以概括。或者,也許不是。也許這是應用特定的?)

回答

3

使用WaitGroup

以下代碼使用兩個WaitGroups。主要功能使用wgTest等待print_if_prime函數完成。一旦完成,它將關閉通道以打破打印程序中的for循環。主要功能使用wgPrint等待打印完成。

package main 

import (
    "fmt" 
    "sync" 
) 

func main() { 
    c := make(chan int) 
    var wgPrint, wgTest sync.WaitGroup 

    wgPrint.Add(1) 
    go func(wg *sync.WaitGroup) { 
    defer wg.Done() 
    for n := range c { 
     fmt.Print(" ", n) 
    } 
    }(&wgPrint) 

    for n := 2; n < 1000; n++ { 
    wgTest.Add(1) 
    go print_if_prime(&wgTest, n, c) 
    } 

    wgTest.Wait() 
    close(c) 
    wgPrint.Wait() 
} 

func print_if_prime(wg *sync.WaitGroup, n int, channel chan int) { 
    defer wg.Done() 
    for d := 2; d*d <= n; d++ { 
    if n%d == 0 { 
     return 
    } 
    } 
    channel <- n 
} 

playground example

+0

這是利用等待的用戶組_really_很好的例子。 –

相關問題