如何动态决定处理任务的 goroutines 数量

How to dynamically decide on number of goroutines working on a task

我写了一个伪代码来演示目的。

代码中有2个通道和3个协程。

1 goroutine 正在根据它们是否可以被 100 整除而没有余数来生成数字:

2 个 goroutines 是这些通道的消费者:

现在很明显,一个 goroutine 比另一个 goroutine 多 99 倍的工作要做。 这在 Go 中是如何处理的?如果一个 goroutine 比其他 goroutine 工作得更多,这个 goroutine 是否有更多 CPU 时间? 还是我应该处理这种情况,例如为资源消耗量更大的频道创建 99 个 goroutine? (为了争论,这些工作被认为是相同的)

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)

    go generator(ch1, ch2)
    go handler(ch1)
    go handler2(ch2)

    time.Sleep(1*time.Second)
}

func generator(chan1, chan2 chan int){
    for i:=0 ; ; i++{
        if i%100 == 0{
            chan1 <- i
        }else{
            chan2 <- i
        }
    }
}

func handler(number chan int){
    for _ = range number{
        num := <- number
        fmt.Println("Number divided by 100 is 0. ", num)
    }
}

func handler2(number chan int){
    for _ = range number{
        num := <- number
        fmt.Println("Number divided by 100 is not 0. ", num)
    }
}

goroutine 获得多少 CPU 资源取决于很多因素。

我们一般可以说的是,仅处理可被 100 整除的数字的 goroutine 很可能会比另一个 goroutine 等待更多。你不应该担心这个,等待通道上的元素不需要 CPU 资源,所以如果你有 "enough" 其他有工作要做的 goroutines,他们可以利用你的 CPU.

你的例子很简单,原因很明显,但在现实生活中,将你的任务抽象为一般任务(例如,处理任何数字都可能是一项任务)、创建和使用一般工作池会更有利可图,并将所有要执行的任务发送到池中。这样,无论池中有多少 goroutine,如果有工作要做并且有空闲(等待)goroutine,它将承担任务,尽可能利用您的 CPU 资源。作业处理器(执行者)应该知道如何处理 100101.

的数字

有关如何实现此类 goroutine 池的示例,请参阅

如果 ch2 上没有任何内容可供读取,handler2 将不执行任何操作。同时,handler1 忙于处理它从 ch1 读取的内容。这会消耗更多 CPU 时间。

有趣的是从启动三个 Goroutine 到数据在通道上可用需要多长时间。 generator 可能在 handler1handler2 准备好从通道读取之前完成所有工作。在这种情况下,handler2 将很快完成其工作,而 handler1 仍有工作要做。

您当然可以创建更多 handler1 的 Goroutine,它们将以一种循环方式处理数据。根据工作的性质,这可能会提高或降低整体性能。

顺便说一句,generator 应该 close ch1ch2 都写好了。