Go如何保证gorountine执行完毕后继续执行

栏目: Go · 发布时间: 5年前

内容简介:Gorountine和channel是go语言最核心的功能,这个功能保证了go强大的并发执行能力。如果你想在你继续执行你的goroutine之前等待所有的goroutines执行完毕,你该如何使用go语言解决这样一个问题呢?下面,我将给出三中解决方案。其中,最有解决方案是

Go如何保证gorountine执行完毕后继续执行

Gorountine和channel是 go 语言最核心的功能,这个功能保证了go强大的并发执行能力。如果你想在你继续执行你的goroutine之前等待所有的goroutines执行完毕,你该如何使用go语言解决这样一个问题呢?

下面,我将给出三中解决方案。其中,最有解决方案是 sync.WaitGroup

程序函数等待

利用time包中的Sleep方法等待一段时间,这样就引起另外一个问题,到底该等待多久呢?

下面是程序的实现。

func receiveMsg(){
    msg := make(chan string)
    go func(){
        time.Sleep(time.Second * 1)
        msg <- "goroutine 1"
    }()

    go func(){
        time.Sleep(time.Second * 2)
        msg <- "goroutine 2"
    }()
    go func(){
        time.Sleep(time.Second * 3)
        msg <- "goroutine 3"
    }()

    go func(){
        for i := range msg {
            fmt.Println("message :", i)
        }
    }()
    time.Sleep(time.Second * 4)
}


func main() {
    receiveMsg()
}

功能上解决了问题,但是,如果没法知道所有的goroutine总共执行,还是没有从根本上解决问题。利用channel,可以有一个改良版的解决方案。

channel等待

首先,看看具体的程序实现。

func receiveMsg2(){
    msg := make(chan string)
    done := make(chan bool)

    go func(){
        time.Sleep(time.Second * 3)
        msg <- "goroutine 1"
        done <- true
    }()
    go func(){
        time.Sleep(time.Second * 2)
        msg <- "goroutine 2"
        done <- true
    }()
    go func(){
        time.Sleep(time.Second * 1)
        msg <- "goroutine 3"
        done <- true
    }()
    go func(){
            //This statement is to make sure that all message is received.
        time.Sleep(time.Second * 3)
        for i := range msg {
            fmt.Println("message :", i)
        }
    }()

    for j := 0 ; j < 3; j++ {
        <-done
    }

}


func main() {
    receiveMsg2()
}

从上面程序而言,程序添加了 time.Sleep(time.Second * 1) 。添加这行代码是为了保证消息被完全接受(打印到控制台)。由这个程序的解决方案引出了另外一个问题:加入我们不知道到底有多少个goroutine该怎么办?

sync.WaitGroup

sync 包下面的 WaitGroup 结构体就是为解决这样的问题而设计的,官方定义如下:

A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.

使用 sync.WaitGroup 有四个步骤:

1. 创建一个新的 sync.WaitGroup 实例 wg (假定代码,下面描述要用到);

2. 当需要使用goroutine的时候,调用 wg.Add(1) (使用一次调用一次,如果知道到有N个goroutine,可以直接设置对应的N个);

3. 当goroutine执行完毕前,需要告诉WaitGroup执行完毕,调用对应代码 defer wg.Done()

4. 在需要等待所有goroutine执行完毕时,调用代码 wg.Wait()

func receiveMsg3(){
    msg := make(chan string)
    var wg sync.WaitGroup

    wg.Add(3)
    go func(){
        defer wg.Done()
        time.Sleep(time.Second * 3)
        msg <- "goroutine 1"
    }()
    go func(){
        defer wg.Done()
        time.Sleep(time.Second * 2)
        msg <- "goroutine 2"
    }()
    go func(){
        defer wg.Done()
        time.Sleep(time.Second * 1)
        msg <- "goroutine 3"
    }()
    go func(){
        time.Sleep(time.Second * 3)
        for i := range msg {
            fmt.Println("message :", i)
        }
    }()
    wg.Wait()
}

func main() {
    receiveMsg3()
}

通过上面的代码就是按照这4个步骤来构建整个函数的,运用 sync.WaitGroup 可以顺利实现并发等待操作。

欢迎订阅微信公众号

Go如何保证gorountine执行完毕后继续执行


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

断点:互联网进化启示录

断点:互联网进化启示录

[美]杰夫·斯蒂贝尔 / 师蓉 / 中国人民大学出版社有限公司 / 2014-11-1 / CNY 49.00

一部神经学、生物学与互联网技术大融合的互联网进化史诗巨著。 我们正置身网络革命中。互联网的每一丝变化都与你我息息相关。当科技变得无处不在时,它就会改变你我。在《断点》一书中,大脑科学家和企业家杰夫·斯蒂贝尔将带领读者来到大脑、生物与技术的交汇处,向读者展示生物学和神经学是如何与互联网技术发生联系的;我们是如何通过生物学上的前车之鉴,来预测互联网的发展的;互联网在经历增长、断点和平衡后又会发生......一起来看看 《断点:互联网进化启示录》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具