我想限制创建的 Goroutine 的最大数量,以避免创建太多的 Goroutine。我们可以通过使用如下所示的方法来实现相同的目的:
var g errgroup.Group
g.SetLimit(10)
for i := 0; i < 1000000; i++ {
i := i
g.Go(func() error {
task(i) //long running task with I/O
return nil
})
}
g.Wait()
我在上面创建了 10 个 goroutine 的限制。仅当前 10 个 Goroutine 之一完成其任务时,下一个 Goroutine(即第 11 个)才会运行。但我希望每当任何 Goroutine 处于等待状态时,第 11 个 Goroutine 也能运行。
我怎样才能在这里实现这一目标?
如果你想限制整个程序的线程数量,那么设置 GOMAXPROCS 是正确的选择。但是,如果您想限制程序某些部分的并发性,那么您可以生成特定数量的工作线程,然后使用通道与它们进行通信。
这是一个例子:
package main
import (
"fmt"
"sync"
"time"
)
const maxWorkers = 3
func worker(inputChannel <-chan int, outputChannel chan<- int, wg *sync.WaitGroup) {
for val := range inputChannel {
fmt.Printf("Working with %d\n", val)
time.Sleep(2 * time.Second)
outputChannel <- val + 1
}
wg.Done()
}
func main() {
workerChannel := make(chan int)
outputChannel := make(chan int)
wg := &sync.WaitGroup{}
//Spawn workers
for i := 0; i < maxWorkers; i++ {
wg.Add(1)
go worker(workerChannel, outputChannel, wg)
}
//Assign work
go func() {
for i := 0; i < 10; i++ {
workerChannel <- i
}
close(workerChannel)
}()
//Close the output channel when the work is done
go func() {
wg.Wait()
close(outputChannel)
}()
//Wait for output
for res := range outputChannel {
fmt.Printf("Got result %d\n", res)
}
}
希望这有帮助!