如何动态确定执行任务的goroutine的数量

时间:2019-02-12 11:17:44

标签: go concurrency channel goroutine

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

代码中有2个通道和3个goroutine。

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

  • 如果数字可以被100整除,它将被推到第一个频道。

  • 否则它将其推送到第二个频道。

2个goroutine是这些渠道的使用者:

  • 1个goroutine负责消耗1 ... 99-101 ... 199等数字。

  • 其他goroutine负责100、200、300等。

现在,一个goroutine要做的工作显然比另一个goroutine多了99倍。 Go中如何处理?如果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)
    }
}

2 个答案:

答案 0 :(得分:5)

goroutine获得多少CPU资源取决于很多事情。

我们通常可以说的是,仅处理可被100整除的数字的goroutine最有可能比另一个等待更多。您不必为此担心,等待通道中的元素不需要CPU资源,因此,如果您“有足够数量”的其他goroutine要做工作,它们就可以利用您的CPU。

由于明显的原因,您的示例很简单,但是在实际示例中,将您的任务抽象为一般任务(例如,处理任何数量的任务都可以),创建和使用一般工作人员池以及将所有要执行的任务发送到池中。这样,无论池中有多少个goroutine,如果有工作要做,并且有一个空闲的(正在等待的)goroutine,它将承担任务,并尽可能地利用您的CPU资源。工作处理器(执行者)应该知道如何处理100101这个数字。

有关如何实现此类goroutine池的示例,请参见Is this an idiomatic worker thread pool in Go?

答案 1 :(得分:1)

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

有趣的是,从启动三个Goroutine到通道上的可用数据要花费多长时间。在generatorhandler1准备好从通道读取之前,handler2可能已经完成了所有工作。在这种情况下,handler2很快就会完成工作,而handler1仍有工作要做。

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

顺便说一句,写完所有内容后,generator应该closech1ch2