需要使用协程池?
是否可以无限开多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)
}
使用协程池
有些第三方库实现了协程池,同样也可以达到限制协程数量的目的,比如:
网友评论