【发布时间】:2020-06-06 11:44:55
【问题描述】:
如果通过上下文语义在同一个执行线程中计算需要花费大量时间,我无法弄清楚如何取消任务?
我用这个例子作为参考点 https://golang.org/src/context/context_test.go
这里的目标调用一个doWork,如果doWork计算时间太长,GetValueWithDeadline应该在超时后返回0,或者如果调用者调用cancel取消等待,(这里主要是调用者)或者返回的值在给一个时间窗口。
同样的场景可以用不同的方式完成。 (单独的 goroutine 睡眠、唤醒检查值等、互斥锁上的条件等)但我真的很想了解使用上下文的正确方法。
通道语义我理解但这里无法达到预期的效果,默认情况下 在默认情况下调用 doWork 故障并休眠。
package main
import (
"context"
"fmt"
"log"
"math/rand"
"sync"
"time"
)
type Server struct {
lock sync.Mutex
}
func NewServer() *Server {
s := new(Server)
return s
}
func (s *Server) doWork() int {
s.lock.Lock()
defer s.lock.Unlock()
r := rand.Intn(100)
log.Printf("Going to nap for %d", r)
time.Sleep(time.Duration(r) * time.Millisecond)
return r
}
// I take an example from here and it very unclear where is do work executed
// https://golang.org/src/context/context_test.go
func (s *Server) GetValueWithDeadline(ctx context.Context) int {
val := 0
select {
case <- time.After(150 * time.Millisecond):
fmt.Println("overslept")
return 0
case <- ctx.Done():
fmt.Println(ctx.Err())
return 0
default:
val = s.doWork()
}
return all
}
func main() {
rand.Seed(time.Now().UTC().UnixNano())
s := NewServer()
for i :=0; i < 10; i++ {
d := time.Now().Add(50 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), d)
log.Print(s.GetValueWithDeadline(ctx))
cancel()
}
}
谢谢
【问题讨论】:
标签: go concurrency