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!")
}
相關文章
相關標籤/搜索