标签:存在 经典 语言 经典的 优雅 监控 控制器 多个 main
控制并发有两种经典的方式,一种是WaitGroup,另外一种就是Context。
上面说的这种场景是存在的,比如一个网络请求Request,每个Request都需要开启一个goroutine做一些事情,这些goroutine又可能会开启其他的goroutine。所以我们需要一种可以跟踪goroutine的方案,才可以达到控制他们的目的,这就是Go语言为我们提供的Context,称之为上下文非常贴切,它就是goroutine的上下文。
func main() { ctx, cancel := context.WithCancel(context.Background()) go func(ctx context.Context) { for { select { case <-ctx.Done(): fmt.Println("监控退出,停止了...") return default: fmt.Println("goroutine监控中...") time.Sleep(2 * time.Second) } } }(ctx) time.Sleep(10 * time.Second) fmt.Println("可以了,通知监控停止") cancel() //为了检测监控过是否停止,如果没有监控输出,就表示停止了 time.Sleep(5 * time.Second) }
使用Context控制一个goroutine的例子如上,非常简单,下面我们看看控制多个goroutine的例子,其实也比较简单。
func main() { ctx, cancel := context.WithCancel(context.Background()) go watch(ctx,"【监控1】") go watch(ctx,"【监控2】") go watch(ctx,"【监控3】") time.Sleep(10 * time.Second) fmt.Println("可以了,通知监控停止") cancel() //为了检测监控过是否停止,如果没有监控输出,就表示停止了 time.Sleep(5 * time.Second) } func watch(ctx context.Context, name string) { for { select { case <-ctx.Done(): fmt.Println(name,"监控退出,停止了...") return default: fmt.Println(name,"goroutine监控中...") time.Sleep(2 * time.Second) } } }
示例中启动了3个监控goroutine进行不断的监控,每一个都使用了Context进行跟踪,当我们使用cancel
函数通知取消时,这3个goroutine都会被结束。这就是Context的控制能力,它就像一个控制器一样,按下开关后,所有基于这个Context或者衍生的子Context都会收到通知,这时就可以进行清理操作了,最终释放goroutine,这就优雅的解决了goroutine启动后不可控的问题。
转载至: http://www.flysnow.org/2017/05/12/go-in-action-go-context.html
标签:存在 经典 语言 经典的 优雅 监控 控制器 多个 main
原文地址:https://www.cnblogs.com/vincenshen/p/9496717.html