78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
|
|
// Package routineCtrlUtil
|
|||
|
|
//
|
|||
|
|
// @description: 协程控制-用于海量循环中,限制并发的最大同时执行协程数
|
|||
|
|
// @author:
|
|||
|
|
// @revision history:
|
|||
|
|
// @create date: 2022-02-23 17:23:06
|
|||
|
|
package routineCtrlUtil
|
|||
|
|
|
|||
|
|
import "sync"
|
|||
|
|
|
|||
|
|
// RoutineCtrl
|
|||
|
|
//
|
|||
|
|
// @description: 控制同时运行的协程数
|
|||
|
|
type RoutineCtrl struct {
|
|||
|
|
wg *sync.WaitGroup
|
|||
|
|
chNum chan struct{}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Run
|
|||
|
|
//
|
|||
|
|
// @description: 循环内待执行的协程,封装在f函数参数内执行。f函数的最大并发运行数受New参数maxNum限制
|
|||
|
|
// 注意:*** 待执行函数引用外变变量,程序可能会出现不符合逻辑的结果(外部变量变化时,闭包函数获取到的是变化后的变量值) ***
|
|||
|
|
// *** 闭包函数避坑说明 ***
|
|||
|
|
// 方式1)将待执行函数内使用的外部变量,用参数传入,可避免不符合逻辑的结果
|
|||
|
|
// 方式2)将待执行函数内使用的外部变量,使用一个临时局部变量将其值“固定”下来,闭包内使用临时局部变量(临时局部变量不会再被修改)
|
|||
|
|
// 示例:routine_ctrl_test.go -> TestRoutineCtrl
|
|||
|
|
//
|
|||
|
|
// parameter:
|
|||
|
|
//
|
|||
|
|
// @receiver rtCtrl:
|
|||
|
|
// @f: 循环内待执行的协程
|
|||
|
|
//
|
|||
|
|
// return:
|
|||
|
|
func (rtCtrl *RoutineCtrl) Run(f func(interface{}), arg interface{}) {
|
|||
|
|
rtCtrl.wg.Add(1)
|
|||
|
|
rtCtrl.chNum <- struct{}{}
|
|||
|
|
go func() {
|
|||
|
|
defer func() {
|
|||
|
|
<-rtCtrl.chNum
|
|||
|
|
rtCtrl.wg.Done()
|
|||
|
|
recover() // 异常捕获
|
|||
|
|
}()
|
|||
|
|
|
|||
|
|
f(arg) // 调用实际函数体
|
|||
|
|
}()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Wait
|
|||
|
|
//
|
|||
|
|
// @description: 在循环外面等待所有协程执行结束后返回
|
|||
|
|
//
|
|||
|
|
// parameter:
|
|||
|
|
//
|
|||
|
|
// @receiver rtCtrl:
|
|||
|
|
//
|
|||
|
|
// return:
|
|||
|
|
func (rtCtrl *RoutineCtrl) Wait() {
|
|||
|
|
rtCtrl.wg.Wait()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// New
|
|||
|
|
//
|
|||
|
|
// @description: 产生一个协程控制对象
|
|||
|
|
//
|
|||
|
|
// parameter:
|
|||
|
|
//
|
|||
|
|
// @maxNum: 限制调用Run时的f函数的最大运行协程数
|
|||
|
|
//
|
|||
|
|
// return:
|
|||
|
|
//
|
|||
|
|
// @*RoutineCtrl:
|
|||
|
|
func New(maxNum int) *RoutineCtrl {
|
|||
|
|
return &RoutineCtrl{
|
|||
|
|
wg: &sync.WaitGroup{},
|
|||
|
|
chNum: make(chan struct{}, maxNum),
|
|||
|
|
}
|
|||
|
|
}
|