Go 控制Goroutine的数量

482 次浏览次阅读
没有评论

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())
}
正文完
 0
评论(没有评论)