goProject/trunk/goutil/routineCtrlUtil/routineCtrl.go
皮蛋13361098506 1b77f62820 初始化项目
2025-01-06 16:01:02 +08:00

78 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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),
}
}