错误的写法:
这里的<-ch 是为了从channel 中读取 数据,为了不使channel通道被写满,阻塞 go 协程数的创建。但是请注意,go workForDraw(v, &wg) 是不阻塞后续的<-ch 执行的,所以就一直go workForDraw(v, &wg) 拉起新的协程。这么是达不到控制协程并发数10 的目的
正确的写法:
直接将<-ch 写入workForDraw 方法里面的最后,这样只有 该 go 协程的任务 workForDraw 完成之后才会执行 <-ch ,使channel管道中的缓冲释放一个。
这样就把 <-ch 和 go 协程持有的任务 workForDraw 强制绑定,只有完成任务才会 <-ch ,如果不完成,只要channel通道的缓冲不满10 就可以继续创建新的go 协程持有workForDraw。直到缓冲满到10 为止
func ListenRedisQue() {
ch := make(chan int, 10)
var wg sync.WaitGroup
for {
keyData, err := config.GetRedisClient().Keys(global.RedisQueueKey + "*").Result()
fmt.Println("ListenRedisQue start for", keyData)
if err != nil {
fmt.Println("redis queue empty!!")
return
}
for _, v := range keyData {
ch <- 1
wg.Add(1)
go workForDraw(v, &wg, ch)
}
wg.Wait()
}
}
func workForDraw(queueKey string, wg *sync.WaitGroup, ch chan int) {
defer wg.Done()
<-ch
}
另外切记 在for 循环中,一定不能初始化 db,或者其他消耗资源,可循环使用的动作,要将初始化提到for之外,将资源以变量或者指针形式传入 for 逻辑内部使用