【问题标题】:Limiting number of go routines running限制运行的 goroutine 的数量
【发布时间】:2019-03-17 02:08:06
【问题描述】:

我有一个要处理的 url 列表,但我想一次运行最大数量的 goroutine。例如,如果我有 30 个 url,我只希望 10 个 goroutine 并行工作。

我的尝试如下:

parallel := flag.Int("parallel", 10, "max parallel requests allowed")
flag.Parse()
urls := flag.Args()

var wg sync.WaitGroup
client := rest.Client{}

results := make(chan string, *parallel)

for _, url := range urls {
    wg.Add(1)
    go worker(url, client, results, &wg)
}

for res := range results {
    fmt.Println(res)
}

wg.Wait()
close(results)

我的理解是,如果我创建一个并行大小的缓冲通道,那么代码将阻塞,直到我读取结果通道,这将解除阻塞我的代码并允许生成另一个 goroutine。 但是,在处理完所有 url 之后,这段代码似乎并没有被阻塞。有人可以向我解释如何使用通道来限制运行的 goroutine 的数量吗?

【问题讨论】:

  • 有一种标准技术可以实现这一点,名为“工人池”,有助于限制/控制工人的数量。这种技术用于不同的编程语言,包括 Go、Elixir 和 Erlang。我在这里写了一个这样的工作池:github.com/dc0d/workerpool

标签: go goroutine


【解决方案1】:

创建所需数量的工作人员,而不是每个 url 一名工作人员:

parallel := flag.Int("parallel", 10, "max parallel requests allowed")
flag.Parse()

// Workers get URLs from this channel
urls := make(chan string) 

// Feed the workers with URLs
go func() {
    for _, u := range flag.Args() {
        urls <- u
    }
    // Workers will exit from range loop when channel is closed
    close(urls)
}()

var wg sync.WaitGroup
client := rest.Client{}

results := make(chan string)

// Start the specified number of workers.
for i := 0; i < *parallel; i++ {
    wg.Add(1)
    go func() {
        defer wg.Done()
        for url := range urls {
            worker(url, client, results)
        }
    }()
}

// When workers are done, close results so that main will exit.
go func() {
    wg.Wait()
    close(results)
}()

for res := range results {
    fmt.Println(res)
}

【讨论】:

    猜你喜欢
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    相关资源
    最近更新 更多