go 的 goroutine 提供了一种比线程而言更廉价的方式处理并发场景。相比线程,协程占据更小的内存空间,并且由于是在用户态进行调度,上下文切换的代价更小。所以协程更加容易支撑几万几百万的并发。但 goroutine 太多仍会导致调度性能下降、GC 频繁、内存暴涨, 引发一系列问题。
因此本文的目的是学习如何实现一个go协程池。
借鉴java的线程池,定义如下的结构体
type GoroutinePool struct {
name string
coreSize uint32 //定义有多少协程
taskChan chan func() //类似java的Runable中的run方法
stop bool //是否停止协程池
}
新建一个协程池,通过start方法启动协程。
使用select实现任务的执行和协程的销毁
func NewGoroutinePool(name string, coreSize uint32) *GoroutinePool{
goroutinePool := &GoroutinePool{
name: name,
coreSize: coreSize,
taskChan: make(chan func()),
stop: false,
}
goroutinePool.start()
return goroutinePool
}
func (pool *GoroutinePool) start() {
for i