Go 控制Goroutine的数量

作者: 太阳上的雨天 分类: Go 发布时间: 2022-11-11 10:03

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

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注