21 go并发编程-下

如何等待一组goroutine结束

1. 使用不带缓冲区的channel实现。

原理:
每一个goroutine都往一个channel里写入一个值,而后咱们去遍历这个管道的数值,因为不带缓冲区,那么必须等到写入端写入一个值后,for循环才能循环下去。这样等循环完成后,那么goroutine也都执行完成了。
实现前提:goroutine必须往channel写入一个值,不然for循环的时候会报deadlock的错误!
代码以下所示:线程

// main
package main

import (
    "fmt"
    "time"
)

func process(i int, ch chan bool) {
    fmt.Println("started Goroutine ", i)
    time.Sleep(2 * time.Second)
    fmt.Printf("GoRoutine %d ended\n", i)
    ch <- true //写入一个值,必须写入
}

func main() {
    no := 3
    exitChan := make(chan bool, no)
    for i := 0; i < no; i++ {
        go process(i, exitChan)
    }
    for i := 0; i < no; i++ { // 遍历这个channel
        <-exitChan
    }
    fmt.Println("all goroutines are done!")
}

2. 使用sync.WaitGroup实现。

先说说WaitGroup的用途:它可以一直等到全部的goroutine执行完成,而且阻塞主线程的执行,直到全部的goroutine执行完成。
WaitGroup总共有三个方法:Add(delta int)、Done()、Wait()。简单的说一下这三个方法的做用。code

  1. Add:添加或者减小等待goroutine的数量
  2. Done:至关于Add(-1)
  3. Wait:执行阻塞,直到全部的WaitGroup数量变成0
package main

import (
    "fmt"
    "sync"
    "time"
)

func process(i int, wg *sync.WaitGroup) {
    fmt.Println("started Goroutine ", i)
    time.Sleep(2 * time.Second)
    fmt.Printf("Goroutine %d ended\n", i)
    wg.Done()
}

func main() {
    no := 10
    var wg sync.WaitGroup
    for i := 0; i < no; i++ {
        wg.Add(1)
        go process(i, &wg)
    }
    wg.Wait()
    fmt.Println("all goroutines are done!")
}
相关文章
相关标签/搜索