我写了一个伪代码来演示目的。
代码中有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)
}
}
答案 0 :(得分:5)
goroutine获得多少CPU资源取决于很多事情。
我们通常可以说的是,仅处理可被100整除的数字的goroutine最有可能比另一个等待更多。您不必为此担心,等待通道中的元素不需要CPU资源,因此,如果您“有足够数量”的其他goroutine要做工作,它们就可以利用您的CPU。
由于明显的原因,您的示例很简单,但是在实际示例中,将您的任务抽象为一般任务(例如,处理任何数量的任务都可以),创建和使用一般工作人员池以及将所有要执行的任务发送到池中。这样,无论池中有多少个goroutine,如果有工作要做,并且有一个空闲的(正在等待的)goroutine,它将承担任务,并尽可能地利用您的CPU资源。工作处理器(执行者)应该知道如何处理100
或101
这个数字。
有关如何实现此类goroutine池的示例,请参见Is this an idiomatic worker thread pool in Go?
答案 1 :(得分:1)
如果ch2
上没有要读取的内容,则handler2
不执行任何操作。同时,handler1
忙于处理从ch1
读取的内容。这会消耗更多的CPU时间。
有趣的是,从启动三个Goroutine到通道上的可用数据要花费多长时间。在generator
和handler1
准备好从通道读取之前,handler2
可能已经完成了所有工作。在这种情况下,handler2
很快就会完成工作,而handler1
仍有工作要做。
您当然可以创建更多handler1
的Goroutine,这些Goroutine将以循环方式处理数据。根据工作的性质,这可能会改善或降低整体性能。
顺便说一句,写完所有内容后,generator
应该close
和ch1
都ch2
。