How would you define a pool of goroutines to be executed at once?

后端 未结 3 1969
北荒
北荒 2020-11-30 17:18

TL;DR: Please just go to the last part and tell me how you would solve this problem.

I\'ve begun using Go this morning coming from Python. I want to call a closed-sou

相关标签:
3条回答
  • 2020-11-30 17:27

    I would spawn 4 worker goroutines that read the tasks from a common channel. Goroutines that are faster than others (because they are scheduled differently or happen to get simple tasks) will receive more task from this channel than others. In addition to that, I would use a sync.WaitGroup to wait for all workers to finish. The remaining part is just the creation of the tasks. You can see an example implementation of that approach here:

    package main
    
    import (
        "os/exec"
        "strconv"
        "sync"
    )
    
    func main() {
        tasks := make(chan *exec.Cmd, 64)
    
        // spawn four worker goroutines
        var wg sync.WaitGroup
        for i := 0; i < 4; i++ {
            wg.Add(1)
            go func() {
                for cmd := range tasks {
                    cmd.Run()
                }
                wg.Done()
            }()
        }
    
        // generate some tasks
        for i := 0; i < 10; i++ {
            tasks <- exec.Command("zenity", "--info", "--text='Hello from iteration n."+strconv.Itoa(i)+"'")
        }
        close(tasks)
    
        // wait for the workers to finish
        wg.Wait()
    }
    

    There are probably other possible approaches, but I think this is a very clean solution that is easy to understand.

    0 讨论(0)
  • 2020-11-30 17:28

    try this: https://github.com/korovkin/limiter

     limiter := NewConcurrencyLimiter(10)
     limiter.Execute(func() {
            zenity(...) 
     })
     limiter.Wait()
    
    0 讨论(0)
  • 2020-11-30 17:34

    A simple approach to throttling (execute f() N times but maximum maxConcurrency concurrently), just a scheme:

    package main
    
    import (
            "sync"
    )
    
    const maxConcurrency = 4 // for example
    
    var throttle = make(chan int, maxConcurrency)
    
    func main() {
            const N = 100 // for example
            var wg sync.WaitGroup
            for i := 0; i < N; i++ {
                    throttle <- 1 // whatever number
                    wg.Add(1)
                    go f(i, &wg, throttle)
            }
            wg.Wait()
    }
    
    func f(i int, wg *sync.WaitGroup, throttle chan int) {
            defer wg.Done()
            // whatever processing
            println(i)
            <-throttle
    }
    

    Playground

    I wouldn't probably call the throttle channel "dummy". IMHO it's an elegant way (it's not my invention of course), how to limit concurrency.

    BTW: Please note that you're ignoring the returned error from cmd.Run().

    0 讨论(0)
提交回复
热议问题