等待对于n够程的终止(Wait for the termination of n goroutine

2019-09-03 17:45发布

我要开始一个巨大的够程的数量和等待他们终止。 直观的方式似乎使用的信道要等到所有的人都完成了:

package main

type Object struct {
    //data
}

func (obj *Object) Update(channel chan int) {
    //update data
    channel <- 1
    return
}

func main() {

    channel := make(chan int, n)
    list := make([]Object, n, m)
    for {
        for _, object := range list {
            go object.Update(channel)
        }
        for i := 0; i < n; i++ {
            <-channel
        }
        //now everything has been updated. start again
    }
}

但问题是,物体的数量,因此够程的数量可能会改变。 是否有可能改变一个通道的缓冲区的大小?

有没有可能是更优雅的方式来做到这一点?

Answer 1:

我用WaitGroup作为解决这个问题。 翻译您当前的代码,一些日志要清楚发生了什么:

package main

import "sync"
import "fmt"
import "time"

type Object struct {
    //data
}

func (obj *Object) Update(wg *sync.WaitGroup) {
    //update data
    time.Sleep(time.Second)
    fmt.Println("Update done")
    wg.Done()
    return
}

func main() {
    var wg sync.WaitGroup
    list := make([]Object, 5)
    for {
        for _, object := range list {
            wg.Add(1)
            go object.Update(&wg)
        }
        //now everything has been updated. start again
        wg.Wait()
        fmt.Println("Group done")
    }
}


Answer 2:

在不完全琐碎这个任务,它很容易写一个越野车。 我建议使用在STDLIB一个现成的解决方案- sync.WaitGroup 。 从链接引用:

一个WaitGroup等待够程来完成的集合。 主够程调用添加设置够程等待数。 然后,每完成后,完成的够程运行和调用。 与此同时,等可以用来阻塞,直到所有的够程已经完成。



Answer 3:

@tjameson做了伟大的工作,解释如何使用WaitGroup ,如何给你的一个引用传递WaitGroup对象的功能。 在一个变化我会做他的例子是杠杆defer ,当你Done 。 我觉得这个defer ws.Done()应该在你的函数的第一个语句。

我喜欢WaitGroup的简单性。 不过,我不喜欢,我们需要通过参考够程,因为这将意味着并发逻辑将与您的业务逻辑混合。

所以,我想出了这个通用的功能来解决这个问题对我来说:

// Parallelize parallelizes the function calls
func Parallelize(functions ...func()) {
    var waitGroup sync.WaitGroup
    waitGroup.Add(len(functions))

    defer waitGroup.Wait()

    for _, function := range functions {
        go func(copy func()) {
            defer waitGroup.Done()
            copy()
        }(function)
    }
}

所以,你的例子可以用此方式解决:

type Object struct {
    //data
}

func (obj *Object) Update() {
    //update data
    time.Sleep(time.Second)
    fmt.Println("Update done")
    return
}

func main() {
    functions := []func(){}
    list := make([]Object, 5)
    for _, object := range list {
        function := func(obj Object){ object.Update() }(object)
        functions = append(functions, function)
    }

    Parallelize(functions...)        

    fmt.Println("Group done")
}

如果你想使用它,你可以在这里找到它https://github.com/shomali11/util



文章来源: Wait for the termination of n goroutines