您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

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

时间:2020-08-21 10:56:16  来源:  作者:

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

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

参考:https://blog.csdn.net/john_f_lau/article/details/56279803

参考:go语言中文文档:www.topgoer.com

程序函数等待

利用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()
}
12345678910111213141516171819202122232425262728

功能上解决了问题,但是,如果没法知道所有的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()
}
12345678910111213141516171819202122232425262728293031323334353637

从上面程序而言,程序添加了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()
}
1234567891011121314151617181920212223242526272829303132

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



Tags:gorountine   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Gorountine和channel是go语言最核心的功能,这个功能保证了go强大的并发执行能力。如果你想在你继续执行你的goroutine之前等待所有的goroutines执行完毕,你该如何使用go语言解...【详细内容】
2020-08-21  Tags: gorountine  点击:(128)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(12)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(196)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(236)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(272)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条