让sync.WaitGroup支持并发数量限制

简介: 让sync.WaitGroup支持并发数量限制

让sync.WaitGroup支持并发数量限制



重新定义WaitGroup


重新定义WaitGroup,目的就是为了支持并发数量限制,跟以往不确定并发相比,重新构造的WaitGroup可以限制并发数量和查看pending数量。


代码


// WaitGroup 实现一个简单的goroutine池
type WaitGroup struct {
 size      int
 pool      chan byte
 waitCount int64
 waitGroup sync.WaitGroup // 底层还是利用sync.WaitGroup去做并发控制
}
// NewWaitGroup 创建一个带有size的并发池 当size为<=0时,直接走sync.WaitGroup逻辑
func NewWaitGroup(size int) *WaitGroup {
 wg := &WaitGroup{
  size: size,
 }
 if size > 0 {
  wg.pool = make(chan byte, size)
 }
 return wg
}
// BlockAdd 将“1”推入并发池中,如果池已满,则阻塞,这样就打到了限制并发的目的
func (wg *WaitGroup) BlockAdd() {
 if wg.size > 0 {
  wg.pool <- 1
 }
 wg.waitGroup.Add(1)
}
// Done 代表一个并发结束
func (wg *WaitGroup) Done() {
 if wg.size > 0 {
  <-wg.pool
 }
 wg.waitGroup.Done()
}
// Wait 等待所有并发goroutine结束
func (wg *WaitGroup) Wait() {
 wg.waitGroup.Wait()
}
// PendingCount 返回所有pending状态的goroutine数量
func (wg *WaitGroup) PendingCount() int64 {
 return int64(len(wg.pool))
}
func main() {
 urls := []string{
  "https://www.a.com/",
  "https://www.b.com",
  "https://www.c.com",
  "https://www.d.com/",
  "https://www.e.com",
  "https://www.f.com",
 }
 wg := NewWaitGroup(2)
 for _, url := range urls {
  wg.BlockAdd()
  go func(url string) {
   defer wg.Done()
   res, err := http.Get(url)
   if err != nil {
    fmt.Printf("%s: result: %v\n", url, err)
    return
   }
   defer res.Body.Close()
  }(url)
 }
 wg.Wait()
 fmt.Println("Finished")
}


结果

640.png


小结


其实原则上我们用sync.WaitGroup可以满足并发控制,但是有些业务场景需要限制并发数量,而语言本身提供的又无法满足,所以这里就简单封装,实现了WaitGroup的并发限制,当然,这只是一小步,如果大家有兴趣,可以在其之上加上context,这样就可以满足超时控制和取消了。

相关文章
一日一技:使用 asyncio 如何限制协程的并发数
一日一技:使用 asyncio 如何限制协程的并发数
1093 0
一日一技:使用 asyncio 如何限制协程的并发数
|
6月前
|
Go
使用 sync.Cond 来协调并发 goroutine 的访问共享资源
使用 sync.Cond 来协调并发 goroutine 的访问共享资源
|
3月前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
6月前
|
设计模式 Java Go
Go - 使用 sync.WaitGroup 来实现并发操作
Go - 使用 sync.WaitGroup 来实现并发操作
54 2
|
6月前
|
存储 设计模式 Java
Go - 使用 sync.Pool 来减少 GC 压力
Go - 使用 sync.Pool 来减少 GC 压力
76 0
|
缓存 Go
控制goroutine 的并发执行数量
控制goroutine 的并发执行数量
159 0
|
Go
Go并发控制sync.WaitGroup
Go语言使用sync.WaitGroup控制并发的顺序,用于任务的同步,等待所有并发任务完成,再持续执行。
84 0
|
9月前
|
Go
动态并发控制:sync.WaitGroup的灵活运用
动态并发控制:sync.WaitGroup的灵活运用
150 0
动态并发控制:sync.WaitGroup的灵活运用
|
Cloud Native 安全 测试技术
GO 语言处理并发的时候我们是选择sync还是channel
GO 语言处理并发的时候我们是选择sync还是channel
goroutine+channel实现对多个goroutine的顺序执行
goroutine+channel实现对多个goroutine的顺序执行