您是想追踪特定的 y 协程,还是 x 中的任意 y?您的标准是什么?
更新:
1. 如果您可以控制选择匹配 y 协程的任何标准:
您可以通过将指针参数传递到协程中,并根据条件在协程内部执行
wp.wg.Add(1)
和
wp.wg.Done()
来实现。如果无法在协程外部检查条件,则可以这样做。
以下是示例代码。如果您提供更多细节,我们将能够提供更具体的建议。
func sampleGoroutine(z int, b string, wg *sync.WaitGroup){
defer func(){
if contition1{
wg.Done()
}
}
if contition1 {
wg.Add(1)
}
}
func main() {
wg := sync.WaitGroup{}
for i := 0; i < x; i++ {
go sampleGoroutine(1, "one", &wg)
}
wg.Wait()
}
2. 如果您无法控制哪些协程,只想要第一个 y:
根据您的评论,您无法/不想选择任何特定的 goroutines,而是想要完成最快的那些。如果您希望以通用方式执行此操作,可以使用下面适合您用例的自定义 waitGroup 实现。 (但它不是安全复制的。也没有/需要 wg.Add(int)方法)
type CountedWait struct {
wait chan struct{}
limit int
}
func NewCountedWait(limit int) *CountedWait {
return &CountedWait{
wait: make(chan struct{}, limit),
limit: limit,
}
}
func (cwg *CountedWait) Done() {
cwg.wait <- struct{}{}
}
func (cwg *CountedWait) Wait() {
count := 0
for count < cwg.limit {
<-cwg.wait
count += 1
}
}
可以用于以下情况:
func sampleGoroutine(z int, b string, wg *CountedWait) {
success := false
defer func() {
if success == true {
fmt.Printf("goroutine %d finished successfully\n", z)
wg.Done()
}
}()
fmt.Printf("goroutine %d started\n", z)
time.Sleep(time.Second)
if rand.Intn(10)%2 == 0 {
success = true
}
}
func main() {
x := 10
y := 3
wg := NewCountedWait(y)
for i := 0; i < x; i += 1 {
go sampleGoroutine(i, "something", wg)
}
wg.Wait()
fmt.Printf("%d out of %d goroutines finished successfully.\n", y, x)
}
3. 您还可以将context
与2结合使用,以确保剩余的goroutine不会泄漏
由于有一些长时间的休眠,您可能无法在play.golang上运行此代码。
以下是示例输出:
(请注意,可能会有多个y = 3的goroutine标记为Done,但只等待3个完成)
goroutine 9已启动
goroutine 0已启动
goroutine 1已启动
goroutine 2已启动
goroutine 3已启动
goroutine 4已启动
goroutine 5已启动
goroutine 5标记为done
goroutine 6已启动
goroutine 7已启动
goroutine 7标记为done
goroutine 8已启动
goroutine 3标记为done
在成功完成10个goroutine中的3个后继续。
goroutine 9将被取消,因为取消
goroutine 8将被取消,因为取消
goroutine 6将被取消,因为取消
goroutine 1将被取消,因为取消
goroutine 0将被取消,因为取消
goroutine 4将被取消,因为取消
goroutine 2将被取消,因为取消
Play链接
- https://play.golang.org/p/l5i6X3GClBq
- https://play.golang.org/p/Bcns0l9OdFg
- https://play.golang.org/p/rkGSLyclgje
y
是固定的,还是由计算结果动态确定的? - Cosmic Ossifrage