前言
Go 的 goroutine 提供了一种较线程而言更廉价的方式处理并发场景, go 使用二级线程的模式, 将 goroutine 以 M:N 的形式复用到系统线程上, 节省了 cpu 调度的开销, 也避免了用户级线程(协程)进行系统调用时阻塞整个系统线程的问题。
但在实际的开发中如果待执行的tasks数量过多,可能带来的问题就是goroutine数量激增进而导致调度性能下降、GC 频繁、内存暴涨, 引发一系列问题。在面临这样的场景时, 限制 goroutine 的数量、重用 goroutine 显然很有价值。所以可以通过一个goroutine池来对所有的tasks进行排队执行,类似下面就是一个简单的goroutine池,通过定量的goroutine来进行任务的消费。设计下面的协程池有三个重点问题是需要重点考虑到的
1.如何确保任务全部都被消费完?
2.子goroutine发生panic如何处理?
3.子goroutine如果全部发生panic了怎么办?放任死锁吗?
这里并没考虑子goroutine执行时间太长的问题,主要原因我们可以自定义子goroutine的数量,我更希望的是任务能够执行完全而不是任务什么时候执行完,任务执行时间太长应该是业务侧的问题。
代码展示
1 | import ( |
使用方法
1 | ctx := context.Background() |
总结
池化管理自己的goroutine是非常有必要的,可以帮助我们提升开发效率降低异常风险!所以赶紧把你的goroutine管理起来吧