golang中四种方式实现子goroutine与主协程的同步
文章出处:赵从亮---原文地址
如何实现子goroutine与主线程的同步
第一种方式:time.sleep(),这种方式很太死板,就不演示了。
第二种方式:使用channel机制,每个goroutine传一个channel进去然后往里写数据,在再主线程中读取这些channel,直到全部读到数据了子goroutine也就全部运行完了,那么主goroutine也就可以结束了。这种模式是子线程去通知主线程结束。
package mainimport ( "fmt")func main() { var chanTest = make(chan int) var chanMain = make(chan int) go func() { for i := 0; i < 20; i++ { chanTest <- i fmt.Println("生产者写入数据", i) } close(chanTest) }() go func() { for v := range chanTest { fmt.Println("\t消费者读出数据", v) } chanMain <- 666 }() go func() { for v := range chanTest { fmt.Println("\t\t消费者读出数据", v) } chanMain <- 666 }() <-chanMain <-chanMain }
第三种方式:使用context中cancel函数,这种模式是主线程去通知子线程结束。
package mainimport ( "context" "fmt" "time")func gen(ctx context.Context) <-chan int { dst := make(chan int) n := 1 go func() { for { select { case <-ctx.Done(): fmt.Println("i exited") return // returning not to leak the goroutine case dst <- n: n++ } } }() return dst }func test() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() // cancel when we are finished consuming integers intChan := gen(ctx) for n := range intChan { fmt.Println(n) if n == 5 { break } } }func main() { test() time.Sleep(time.Hour) }
第四种方式:sync.WaitGroup模式,Add方法设置等待子goroutine的数量,使用Done方法设置等待子goroutine的数量减1,当等待的数量等于0时,Wait函数返回。
//使用golang中sync.WaitGroup来实现协程同步 package main import ( "fmt" "net/http" "io/ioutil" "time" "os" "sync" ) var waitGroup = new(sync.WaitGroup) func download(i int ){ url := fmt.Sprintf("http://pic2016.ytqmx.com:82/2016/0919/41/%d.jpg", i) fmt.Printf("开始下载:%s\n", url) res,err := http.Get(url) if err != nil || res.StatusCode != 200{ fmt.Printf("下载失败:%s", res.Request.URL) } fmt.Printf("开始读取文件内容,url=%s\n", url) data ,err2 := ioutil.ReadAll(res.Body) if err2 != nil { fmt.Printf("读取数据失败") } ioutil.WriteFile(fmt.Sprintf("pic2016/1_%d.jpg", i), data, 0644) //计数器-1 waitGroup.Done() } func main() { //创建多个协程,同时下载多个图片 os.MkdirAll("pic2016", 0666) now := time.Now() for i :=1; i<24; i++ { //计数器+1 waitGroup.Add(1) go download(i) } //等待所有协程操作完成 waitGroup.Wait() fmt.Printf("下载总时间:%v\n", time.Now().Sub(now)) }
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦