go context处理单个请求的多个goroutine详解
原创
©著作权归作者所有:来自51CTO博客作者ghostwritten的原创作品,请联系作者获取转载授权,否则将追究法律责任
参考资料:
golang服务器开发利器 context用法详解https://github.com/go-training/training/tree/master/example35-goroutine-with-contextcontext使用
控制并发的两种方式
场景1:多个goroutine执行同一件事
waitGroup使用
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func() {
time.Sleep(2 * time.Second)
fmt.Println("job 1 done.")
wg.Done()
}()
go func() {
time.Sleep(1 * time.Second)
fmt.Println("job 2 done.")
wg.Done()
}()
wg.Wait()
fmt.Println("All Done.")
}
$ go run con3.go
job 2 done.
job 1 done.
All Done.
场景2: 当主动通知停止?如何做?
使用channel + select
package main
import (
"fmt"
"time"
)
func main() {
stop := make(chan bool)
go func() {
for {
select {
case <-stop:
fmt.Println("got the stop channel")
return
default:
fmt.Println("still working")
time.Sleep(1 * time.Second)
}
}
}()
time.Sleep(5 * time.Second)
fmt.Println("stop the gorutine")
stop <- true
time.Sleep(5 * time.Second)
}
$ go run con4.go
still working
still working
still working
still working
still working
stop the gorutine
got the stop channel
当多个goroutine或goroutine中有goroutine
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go func() {
for {
select {
case <-ctx.Done():
fmt.Println("got the stop channel")
return
default:
fmt.Println("still working")
time.Sleep(1 * time.Second)
}
}
}()
time.Sleep(5 * time.Second)
fmt.Println("stop the gorutine")
cancel()
time.Sleep(5 * time.Second)
}
$ go run con5.go
still working
still working
still working
still working
still working
stop the gorutine
got the stop channel
多个goroutine
package main
import (
"context"
"fmt"
"time"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
go worker(ctx, "node01")
go worker(ctx, "node02")
go worker(ctx, "node03")
time.Sleep(5 * time.Second)
fmt.Println("stop the gorutine")
cancel()
time.Sleep(5 * time.Second)
}
func worker(ctx context.Context, name string) {
for {
select {
case <-ctx.Done():
fmt.Println(name, "got the stop channel")
return
default:
fmt.Println(name, "still working")
time.Sleep(1 * time.Second)
}
}
}
$ go run con6.go
node03 still working
node01 still working
node02 still working
node03 still working
node02 still working
node01 still working
node01 still working
node03 still working
node02 still working
node02 still working
node01 still working
node03 still working
node03 still working
node02 still working
node01 still working
stop the gorutine
node01 got the stop channel
node03 got the stop channel
node02 got the stop channel