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())
}