【发布时间】:2021-03-16 02:45:54
【问题描述】:
我有一个函数应该最多生成 N 个 goroutine,然后每个 goroutine 将从作业通道读取并进行一些计算。但是需要注意的是,如果计算花费的时间超过 X,请结束该计算并继续进行下一个计算。
func doStuff(){
rules := []string{
"a",
"b",
"c",
"d",
"e",
"f",
"g",
}
var (
jobs = make(chan []string, len(rules))
res = make(chan bool, len(rules))
matches []string
)
w := func(jobs <-chan []string, results chan<- bool) {
for j := range jobs {
k, id := j[0], j[1]
if id == "c" || id == "e" {
time.Sleep(time.Second * 5)
}
m := match(k, id)
res <- m
}
}
N := 2
for i := 0; i < N; i++ {
go w(jobs, res)
}
for _, rl := range rules {
jobs <- []string{"a", rl}
}
close(jobs)
for i := 0; i < len(rules); i++ {
select {
case match := <-res:
matches = append(matches, match)
case <-time.After(time.Second):
}
}
fmt.Println(matches)
}
预期结果是:
[a, b, d, f, g]
但我得到的是:
[a, b, d]
由于睡眠,似乎在其中一个 goroutine 可以完全完成之前从结果通道中读取结束。所以我添加了一个带有截止日期的上下文,但现在它无限期挂起:
w := func(jobs <-chan []string, results chan<- string) {
for j := range jobs {
ctx, c := context.WithDeadline(context.Background(), time.Now().Add(time.Second*2))
defer c()
k, id := j[0], j[1]
if id == "c" || id == "e" {
time.Sleep(time.Second * 5)
}
m := match(k, id)
select {
case res <- m:
case <-ctx.Done():
fmt.Println("Canceled by timeout")
continue
}
}
}
我已经阅读了其他关于在发生超时时完全杀死 goroutine 的问题,但找不到任何关于超时时跳过的内容。
【问题讨论】:
标签: go