go 协程并发数控制

错误的写法:
这里的<-ch 是为了从channel 中读取 数据,为了不使channel通道被写满,阻塞 go 协程数的创建。但是请注意,go workForDraw(v, &wg) 是不阻塞后续的<-ch 执行的,所以就一直go workForDraw(v, &wg) 拉起新的协程。这么是达不到控制协程并发数10 的目的
go 协程并发数控制_第1张图片

正确的写法:
直接将<-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 
}

go 协程并发数控制_第2张图片
另外切记 在for 循环中,一定不能初始化 db,或者其他消耗资源,可循环使用的动作,要将初始化提到for之外,将资源以变量或者指针形式传入 for 逻辑内部使用

你可能感兴趣的:(golang,开发语言,后端,go,协程并发控制)