golang是原生支持高并发的语言,它的并发是通过协程实现的,对于上千个任务,我们一般会通过将其分割成多组任务后,对于每组任务,开启对应数目的协程来运行任务。
1 | package main |
上面就是一种实现高并发运行任务的方法,但是这种方法对协程的控制不够精细,每组扫描任务都会瞬间启动大量协程,然后逐渐关闭,并不是一个平滑的过程,通过top查看cpu占用时,会发现该程序运行的时候会周期性的大幅度变化,为了实现协程复用,我们采用如下使用channel和sync.WaitGroup相结合的方法
1 | package main |
以上方法通过生产者消费者模式实现协程的复用
可能有人会想,为什么不直接提前分成batchSize组,然后开启batchSize个协程,每个协程循环运行一组任务不就好了?
即
1 | package main |
但是这样并不能高效应用所有协程,每个协程分配的任务可能是不均衡的,有些协程可能运行比较快,就把任务提前运行完了,提前运行完的协程并没有接到新的任务就结束了,白白浪费新开的资源。
而上面协程复用的方法可以源源不断地将信道中的任务送到每个协程中,每个协程可以不间断地进行任务的执行,从而高效利用协程的资源。