zoukankan      html  css  js  c++  java
  • Go语言学习之Go协程:WaitGroup

    我们之前学习了协程和信道,里面有很多例子,当时为了保证main goroutine在所有的goroutine都执行完毕后在退出,我们使用了time.Sleep这种方式

    由于写的demo都是很简单的,sleep个1秒,我们感觉应该是够用的

    但是在实际开发中,我们无法预知,所有的goroutine需要多长时间才能执行完毕,sleep多了 主程序就会阻塞,sleep少了有的子协程的任务无法完成

    我们今天来介绍一下 怎么优雅的处理这种情况

    1.使用信道来标记完成

    信道可以实现多个协程间的通信,那么我们只需要定义一个信道,在任务完成后,往信道中写入true,然后主协程中获取到true,就认为子协程执行完毕

    import "fmt"
    
    func main() {
        done := make(chan bool)
        //开一个协程去执行
        go func() {
            for i := 0; i < 5; i++ {
                fmt.Println(i)
            }
            //执行完毕,往信道里写入true
            done <- true
        }()
        //主协程中如果获取到信道里时true 就退出
        <-done
    }    

    输出如下

    0
    1
    2
    3
    4

    2.使用WaitGroup

    上面使用的方法,在单个协程或者协程数量比较少的时候不会有什么问题,但在协程数多的时候,代码就会很复杂

    更优雅的方式就是使用WaitGroup

    WaitGroup只要实例化了就能用

    var 实例名 sync.WaitGroup 

    实例化完成后,就可以使用它的几个方法:

    1. Add:初始值为0,你传入的值会往计数器上加,这里直接传入子协程的数量
    2. Done: 当某个子协程完成后,可以调用此方法,就会从计数器上减1,通常可以使用defer来调用
    3. Wait: 阻塞当前协程,知道计数器的值归0

    举一个例子

    // Startup the EventRouter
        //这里有一个协程, 所以计数器的值是1
        wg.Add(1)
    //协程 go func() {
    //defer的作用是在eventRouter.run函数执行完,在执行defer的语句,所以这里就是程序执行完了,执行wg.Done()把计数器里的值减1 defer wg.Done() eventRouter.Run(stop) }() // Startup the Informer(s) glog.Infof("Starting shared Informer(s)") sharedInformers.Start(stop) //主协程一直调用wg.Wait()方法阻塞着,直到计数器的值为0在执行后面的代码 wg.Wait()
    //执行这个代码的时候,说明计数器归0了,wg.Wait失效,不会阻塞主协程了 glog.Warningf(
    "Exiting main()") os.Exit(1)
  • 相关阅读:
    xadmin 调用登录报错信息 :takes 0 positional argument but 2 were given解决方法
    xadmin 执行报错 Your STATICFILES_DIRS setting is not a tuple or list
    WordPress的SEO技术
    微信公众平台消息接口星标功能
    微信5.0打飞机怎么取得高分?
    微信公众平台的服务号和订阅号
    微信公众平台开发(58)自定义菜单
    微信公众平台开发(57)Emoji表情符号
    微信公众平台开发(56)优惠券
    微信公众平台开发(55)刮刮乐
  • 原文地址:https://www.cnblogs.com/chadiandianwenrou/p/13886572.html
Copyright © 2011-2022 走看看