简体   繁体   English

长时间运行的 go 例程完成时发出信号

[英]Signal when long running go routines are completed

In this code I have a loop that will run until a certain amount of time has passed.在这段代码中,我有一个循环,它会一直运行到经过一定的时间。 During this time I send a random amount of numbers to a channel to be processed by a longer running go routine.在此期间,我将随机数量的数字发送到一个通道,以便由运行时间更长的 go 例程进行处理。 The problem is the go routines still need to finish doing some kind of task (just sleeping in this example).问题是 go 例程仍然需要完成某种任务(在这个例子中只是睡觉)。 How do I make sure all of the items sent to the numbers channel are completed running and all of the items sent to the messages channel are read?如何确保发送到numbers频道的所有项目都已完成运行并且所有发送到messages频道的项目都已读取?

When I run the code I see 66 numbers should have run and been read.当我运行代码时,我看到 66 个数字应该已经运行并被读取。 But the output only shows 6 out of 66 were run and then read out.但输出仅显示 66 个中的 6 个已运行然后读出。

0s
10ms
20ms
30ms
40ms
50ms
60ms
70ms
80ms
90ms
Ran 3
Ran 5
Ran 1
Ran 0
100ms
Ran 4
Ran 2
110ms
DONE 66

Go Playground去游乐场

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func DoStuff(n int, messages chan string) {
    time.Sleep(time.Duration(100) * time.Millisecond)
    messages <- fmt.Sprintf("Ran %d", n)
}

func Read(messages chan string) {
    for m := range messages {
        fmt.Println(m)
    }
}

func Run(numbers chan int, messages chan string) {
    for n := range numbers {
            go DoStuff(n, messages)
        }   
}

func main() {
    var min = 1
    var max = 10

    var numbers = make(chan int)
    var messages = make(chan string)

    go Read(messages)
    go Run(numbers, messages)

    var n = 0
    for start := time.Now(); ; {
        elapsedTime := time.Since(start)
        fmt.Println(elapsedTime)
        if elapsedTime > time.Duration(100) * time.Millisecond {
            break
        }
        var random = rand.Intn(max - min) + min
        for i := 0; i < random; i++ {
            n++
            numbers <- i
        }
        time.Sleep(time.Duration(10) * time.Millisecond)
    }

    fmt.Println("DONE", n)
}

Use a WaitGroup.使用等待组。 Since numbers represent the incoming work, when you send something to numbers , you can add one to the waitgroup:由于numbers代表传入的工作,当您向numbers发送内容时,您可以向等待组添加一个:

wg.Add(1)
numbers <- i

And as you read from messages, mark that work as done:当您阅读消息时,将这项工作标记为已完成:

func Read(messages chan string, wg *sync.WaitGroup) {
    for m := range messages {
        wg.Done()
        fmt.Println(m)
    }
}

And, wait for the waitgroup to complete in main:并且,等待等待组在 main 中完成:

wg.Wait()
fmt.Println("DONE", n)

Declare your waitgroup where you can pass to goroutines:声明你的等待组,你可以在那里传递给 goroutines:

wg:=sync.WaitGroup{}
go Read(messages,&wg)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM