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

标签 go

在这段代码中,我有一个循环,它将一直运行到经过一定的时间。在此期间,我将随机数量的数字发送到一个 channel ,以由运行时间更长的 go 例程处理。问题是 goroutines 仍然需要完成某种任务(在这个例子中只是休眠)。如何确保所有元素都发送到 numbers channel 已完成运行,所有项目都发送到 messages channel 被读?

当我运行代码时,我看到 66 个数字应该已经运行并被读取。但输出仅显示 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)
}

最佳答案

使用 WaitGroup 。由于numbers代表传入的工作,当你发送一些东西到 numbers ,您可以将一个添加到 WaitGroup :

wg.Add(1)
numbers <- i

当您阅读消息时,将该工作标记为已完成:
func Read(messages chan string, wg *sync.WaitGroup) {
    for m := range messages {
        wg.Done()
        fmt.Println(m)
    }
}

并且,等待 WaitGroup 在 main 中完成:
wg.Wait()
fmt.Println("DONE", n)

声明可以传递给 goroutine 的 WaitGroup :
wg:=sync.WaitGroup{}
go Read(messages,&wg)

关于go - 长时间运行的 go 例程完成时发出信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60196852/

相关文章:

戈朗 : Variable argument

java - Go 和 Java 之间的 IO 性能

docker - 尝试在 docker 中使用 dep 安装依赖项

string - 奇怪的行为,同时变量与函数的输入和输出相同

go - 为什么 `nbytes, err := io.Copy(ioutil.Discard, resp.Body)` 总是返回 0?

go - 为什么我不能将 *Struct 分配给 *Interface?

macos - MacOS 的 Go 1.7 版本错误

go - 相当于Java在GoLang中将Object作为方法参数传递

go - 如何防止递归函数死锁?

go - 从项目根目录运行子文件夹的基准测试