上篇文章中,咱們已經學習了使用context實現控制多個goroutine的退出。
本文將繼續介紹如何使用context實現超時狀況下,讓多個goroutine退出。學習
首先,啓動3個goroutine,分別爲1,2,3。這3個goroutine又分別啓動一個goroutine。.net
一共有6個goroutine,它們之間關係以下:code
task1,2,3被限制在指定時間內結束,即50ms。blog
若是不能按時結束,會觸發超時操做,這樣,task 一、二、3接收到超時信號,取消本身啓動的goroutine(即task11,21,31),而後退出。
最後,全部的goroutine都退出了。get
代碼以下:string
ackage main import ( "context" "fmt" "time" ) func PrintTask(ctx context.Context, taskName string) { for { select { case <- ctx.Done(): fmt.Println("task:", taskName, "ctx error:", ctx.Err()," then task exit...") return default: time.Sleep(1*time.Second) fmt.Println("task:", taskName, " doing something...") } } } func mainTask(ctx context.Context, taskName string) { ctx1, cancel := context.WithCancel(ctx) defer cancel() // create a new task newTaskName := taskName + "1" go PrintTask(ctx1, newTaskName) for { select { case <- ctx.Done(): fmt.Println("task:", taskName, "ctx error:", ctx.Err()," then task exit...") return default: time.Sleep(1*time.Second) fmt.Println("task:", taskName, " doing something...") } } } func main() { ctx := context.Background() timeout := 50*time.Millisecond ctx, _ = context.WithTimeout(ctx, timeout) go mainTask(ctx, "1") go mainTask(ctx, "2") go mainTask(ctx, "3") select{ case <-ctx.Done(): // timeout fmt.Println("main error:", ctx.Err()) } fmt.Println("main exit...") time.Sleep(3*time.Second) }
輸出it
main task error: context deadline exceeded main exit... task: 21 doing something... task: 1 doing something... task: 21 ctx error: context deadline exceeded then task exit... task: 3 doing something... task: 3 ctx error: context deadline exceeded then task exit... task: 1 ctx error: context deadline exceeded then task exit... task: 11 doing something... task: 11 ctx error: context deadline exceeded then task exit... task: 31 doing something... task: 2 doing something... task: 31 ctx error: context deadline exceeded then task exit... task: 2 ctx error: context deadline exceeded then task exit...