Goroutine 虽然体量很小(2kb),理论可以开启上百万个 Goroutine。但也不是多多益善。一旦 Goroutine 过多,会占用大量的 cpu 内存,可能导致服务器速度变慢甚至服务挂掉。
先看一下不控制 Goroutine 数量,看能跑多少
Cpu: 4
Mem: 16G
tasks := math.MaxInt64
for i := 0; i < tasks; i++ {go func(i int) {fmt.Println("go func ", i, " goroutine count = ", runtime.NumGoroutine())
}(i)
}
go func 1327774 goroutine count = 1029277
panic: too many concurrent operations on a single file or socket (max 1048575)
goroutine 1352265 [running]:
internal/poll.(*fdMutex).rwlock(0xc0000540c0, 0x20)
如何控制 Goroutine
type Pool struct {
queue chan int
wg *sync.WaitGroup
}
func NewPool(size int) *Pool {
if size <= 0 {size = 1}
return &Pool{queue: make(chan int, size),
wg: &sync.WaitGroup{},}
}
func (p *Pool) Add(task int) {
for i := 0; i < task; i++ {p.queue <- task}
p.wg.Add(task)
}
func (p *Pool) Done() {
<-p.queue
p.wg.Done()}
func (p *Pool) Wait() {p.wg.Wait()
}
func main() {pool := NewPool(5)
fmt.Println("the NumGoroutine begin is:", runtime.NumGoroutine())
for i := 0; i < 53; i++ {pool.Add(1)
go func() {time.Sleep(time.Second)
fmt.Println("the NumGoroutine continue is:", runtime.NumGoroutine())
pool.Done()}()}
pool.Wait()
fmt.Println("the NumGoroutine done is:", runtime.NumGoroutine())
}
正文完