Goroutine具备如下两个特点
- 体积轻量
- 优质的GMP调度
但并不能随意的创建goroutine,因为迅速的开辟goroutine(不控制并发的 goroutine 数量 )会在短时间内占据操作系统的资源(CPU、内存、文件描述符等)。
- CPU 使用率浮动上涨
- Memory 占用不断上涨。
- 主进程崩溃(被杀掉了)
这些资源实际上是所有用户态程序共享的资源,所以大批的goroutine最终引发的灾难不仅仅是自身,还会关联其他运行的程序。
所以在编写逻辑业务的时候,限制goroutine是我们必须要重视的问题。一般可以通过协程池实现。
package main
import (
"fmt"
"sync"
"time"
)
type Pool struct {
c chan func()
con int
wg sync.WaitGroup
}
func NewPool(con int) *Pool {
return &Pool{
c: make(chan func()),
con: con,
}
}
func usePool() {
p := NewPool(5)
for i := 0; i < p.con; i++ {
go p.worker()
}
for i := 0; i < 10; i++ {
task := func() {
fmt.Println(time.Now())
}
p.c <- task
p.wg.Add(1)
}
close(p.c)
p.wg.Wait()
}
func (Pool *Pool) worker() {
for task := range Pool.c {
task()
Pool.wg.Done()
}
fmt.Println("exit groutine")
}