go 实现生产者与消费者模型,如何判断channel中数据已全部消费?

code

package main

import (
    "fmt"
)

var c = make(chan int, 50)
var count = 0

func main() {
    for i := 0; i < 5; i++ {
        go consumer(i)
    }
    for i := 0; i < 1000; i++ {
        c <- i
    }
    /** here **/
    fmt.Println(count)
}

func consumer(index int) {
    for target := range c {
        fmt.Printf("no.%d:%d\n", index, target)
        count++
    }
}

请问代码中注释处,如何才能确保c中的数据已经全部被消费?(默认time.Sleep()无法保证,不能使用)
如果不能确保的话,那么主线程会提前退出,部分数据就会被抛弃了。

阅读 10.2k
2 个回答

这种可以使用sync里的WaitGroup工具来做等待,也可以单独开个channel来等待。如果只是想单纯的保证goroutine全部执行完毕再退出main,可以定义个相同数量buffer的channel,每个goroutine执行结束后就写入这个channel,而main只要消费等待channel就可以达到阻塞的目的了。

类似这样

var c = make(chan int, 50)
var count = 0
var retChannel = make(chan int,5)
func main() {
    for i := 0; i < 5; i++ {
        go consumer(i)
    }
    for i := 0; i < 1000; i++ {
        c <- i
    }
    /** here **/
    close(c)
    for i := 0; i < 5; i++ {
        <-retChannel
    }
    close(retChannel)
    fmt.Println(count)
}
func consumer(index int) {
    for target := range c {
        fmt.Printf("no.%d:%d\n", index, target)
        count++
    }
    retChannel <- index
}

参考http://blog.csdn.net/kjfcpua/...已解决,使用WaitGroup就解决了

完整代码

package main

import (
    "fmt"
    "sync"
)

var c = make(chan int, 50)
var count = 0
var wg = new(sync.WaitGroup)

func main() {
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go consumer(i)
    }
    for i := 0; i < 1000; i++ {
        c <- i
    }
    wg.Wait()
    close(c)
    /** here **/
    fmt.Println(count)
}

func consumer(index int) {
    for target := range c {
        fmt.Printf("no.%d:%d\n", index, target)
        count++
        if len(c) <= 0 {
            wg.Done()
        }
     }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题