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