【发布时间】:2020-01-06 06:42:27
【问题描述】:
我有一个 goroutine 池,我想从外部杀死其中的一个。
感谢您的帮助
【问题讨论】:
-
例程必须自行终止。它可以从通过
go关键字调用的函数返回,也可以调用runtime.Goexit()。
我有一个 goroutine 池,我想从外部杀死其中的一个。
感谢您的帮助
【问题讨论】:
go 关键字调用的函数返回,也可以调用runtime.Goexit()。
你不能“杀死”一个 goroutine。您可以使用其中一种同步原语或上下文来告诉 goroutine 您希望它结束。
ctx,cancel:=context.WithCancel(context.Background())
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default
}
// Do stuff
}
}(ctx)
...
// Tell that goroutine to stop
cancel()
您也可以使用 sync.atomic:
die:=make([]int32,nGoroutines)
go func(i int) {
if atomic.LoadInt32(&die[i])==1 {
return
}
// Do stuff
if atomic.LoadInt32(&die[i])==1 {
return
}
// Do more stuff
}(0) // 0'th goroutine
...
// Tell goroutine n to stop
atomic.StoreInt32(&die[n],1)
【讨论】:
我找到了答案。有一个名为 Context 的概念,它携带跨越 API 边界和进程之间的截止日期、取消信号和其他请求范围的值。这是示例代码:
type Job struct {
ID int
Context context.Context
Cancel context.CancelFunc
}
var jobs = make(map[int] Job)
func worker(ctx context.Context, index int) {
fmt.Printf("starting job with id %d\n", index)
<-ctx.Done()
}
func main() {
var err error
id := 0
r := gin.Default()
r.POST("/start", func(c *gin.Context) {
var job Job
err := json.NewDecoder(c.Request.Body).Decode(&job)
if err != nil{ fmt.Println(err)}
ctx, cancel := context.WithCancel(context.Background())
job.ID = id
job.Context = ctx
job.Cancel = cancel
jobs[job.ID] = job
c.JSON(http.StatusOK, gin.H{"message": "job received"})
go worker(ctx, job.ID)
id ++
})
r.GET("/cancel/:id", func(c *gin.Context) {
id := c.Param("id")
idInt, err := strconv.Atoi(id)
if err != nil {fmt.Println(err)}
jobs[idInt].Cancel()
})
err = endless.ListenAndServe(":8080", r)
if err != nil{ fmt.Printf("Could not run server : %v", err.Error())}
}
【讨论】:
worker调用了某个函数,而该函数没有返回,worker不会退出。函数本身需要不时检查它是否应该退出。当函数完成后,它可以返回;无需在ctx.Done() 频道上等待,因为不会发送任何内容:它只会被关闭。
你可以使用频道
endRoutine:= make(chan bool)
go func() {
<-endRoutine
}()
//To end one thread waiting on the channel
endRoutine<-true
https://play.golang.org/p/IRARfywOLZX
如果您在循环中处理数据并且需要检查是否应该在每次迭代时退出,您可以使用开关
go func() {
for {
switch {
case <-endRoutine:
return //exit
default:
break
}
}
}()
【讨论】: