美文网首页
go 中 限制 goroutine 数量以及使用协程池

go 中 限制 goroutine 数量以及使用协程池

作者: wayyyy | 来源:发表于2022-01-23 02:51 被阅读0次
需要使用协程池?

Golang 开发需要协程池吗

是否可以无限开多goroutine ?

goroutine 创建需要占用一定量的内存,开一个goroutine 只需要少量的内存空间,几KB,这也是golang能实现百万长链的原因.

但在实际中,goroutine 需要正确的关闭,而不是无限创建后,造成goroutine 泄露,进而引发系统崩溃

如何限制协程数量

网友实现的方案:https://github.com/remeh/sizedwaitgroup

type SizedWaitGroup struct {
    Size int

    current chan struct{}
    wg      sync.WaitGroup
}

func New(limit int) SizedWaitGroup {
    size := math.MaxInt32 // 2^32 - 1
    if limit > 0 {
        size = limit
    }
    
    return SizedWaitGroup{
        Size: size,

        current: make(chan struct{}, size),
        wg:      sync.WaitGroup{},
    }
}

func (s *SizedWaitGroup) Add() {
    s.AddWithContext(context.Background())
}

func (s *SizedWaitGroup) AddWithContext(ctx context.Context) error {
    select {
    case <-ctx.Done():
        return ctx.Err()
    case s.current <- struct{}{}:
        break
    }
    s.wg.Add(1)
    return nil
}

func (s *SizedWaitGroup) Done() {
    <-s.current
    s.wg.Done()
}

func (s *SizedWaitGroup) Wait() {
    s.wg.Wait()
}

使用:

func main() {
    rand.Seed(time.Now().UnixNano())

    // Typical use-case:
    // 50 queries must be executed as quick as possible
    // but without overloading the database, so only
    // 8 routines should be started concurrently.
    swg := sizedwaitgroup.New(8)
    for i := 0; i < 50; i++ {
        swg.Add()
        go func(i int) {
            defer swg.Done()
            query(i)
        }(i)
    }

    swg.Wait()
}

func query(i int) {
    fmt.Println(i)
    time.Sleep(10 * time.Second)
}
使用协程池

有些第三方库实现了协程池,同样也可以达到限制协程数量的目的,比如:

相关文章

网友评论

      本文标题:go 中 限制 goroutine 数量以及使用协程池

      本文链接:https://www.haomeiwen.com/subject/nvnjqrtx.html