Golang併發模型:輕鬆入門select

select在Golang併發中扮演着重要的角色,若是你已經入門了select能夠跳過這篇文章,關注下一篇文章「select進階」。若是想看看,select是如何源自生活的,也能夠閱讀下這篇文章,幾分鐘就能夠讀完。golang

以前的文章都提到過,Golang的併發模型都來自生活,select也不例外。舉個例子:咱們都知道一句話,「吃飯睡覺打豆豆」,這一句話裏包含了3件事:併發

  1. 媽媽喊你吃飯,你去吃飯。函數

  2. 時間到了,要睡覺。測試

  3. 沒事作,打豆豆。spa

在Golang裏,select就是幹這個事的:到吃飯了去吃飯,該睡覺了就睡覺,沒事幹就打豆豆。code

結束髮散,咱們看下select的功能,以及它能作啥。協程

select功能

在多個通道上進行讀或寫操做,讓函數能夠處理多個事情,但1次只處理1個。如下特性也都必須熟記於心:事件

  1. 每次執行select,都會只執行其中1個case或者執行default語句。get

  2. 當沒有case或者default能夠執行時,select則阻塞,等待直到有1個case能夠執行。string

  3. 當有多個case能夠執行時,則隨機選擇1個case執行。

  4. case後面跟的必須是讀或者寫通道的操做,不然編譯出錯。

select長下面這個樣子,由selectcase組成,default不是必須的,若是沒其餘事可作,能夠省略default

 1func main() {
2    readCh := make(chan int, 1)
3    writeCh := make(chan int, 1)
4
5    y := 1
6    select {
7    case x := <-readCh:
8        fmt.Printf("Read %d\n", x)
9    case writeCh <- y:
10        fmt.Printf("Write %d\n", y)
11    default:
12        fmt.Println("Do what you want")
13    }
14}

咱們建立了readChwriteCh2個通道:

  1. readCh中沒有數據,因此case x := <-readCh讀不到數據,因此這個case不能執行。

  2. writeCh是帶緩衝區的通道,它裏面是空的,能夠寫入1個數據,因此case writeCh <- y能夠執行。

  3. case能夠執行,因此default不會執行。

這個測試的結果是

1$ go run example.go
2Write 1

用打豆豆實踐select

來,咱們看看select怎麼實現打豆豆:eat()函數會啓動1個協程,該協程先睡幾秒,事件不定,而後喊你吃飯,main()函數中的sleep是個定時器,每3秒喊你吃1次飯,select則處理3種狀況:

  1. eatCh中讀到數據,表明有人喊我吃飯,我要吃飯了。

  2. sleep.C中讀到數據,表明鬧鐘時間到了,我要睡覺。

  3. default是,沒人喊我吃飯,也不到時間睡覺,我就打豆豆。

 1import (
2    "fmt"
3    "time"
4    "math/rand"
5)
6
7func eat() chan string {
8    out := make(chan string)
9    go func (){
10        rand.Seed(time.Now().UnixNano())
11        time.Sleep(time.Duration(rand.Intn(5)) * time.Second)
12        out <- "Mom call you eating"
13        close(out)
14    }()
15    return out
16}
17
18
19func main() {
20    eatCh := eat()
21    sleep := time.NewTimer(time.Second * 3)
22    select {
23    case s := <-eatCh:
24        fmt.Println(s)
25    case <- sleep.C:
26        fmt.Println("Time to sleep")
27    default:
28        fmt.Println("Beat DouDou")
29    }
30}

因爲前2個case都要等待一會,因此都不能執行,因此執行default,運行結果一直是打豆豆:

1$ go run x.go
2Beat DouDou

如今咱們不打豆豆了,你把default和下面的打印註釋掉,多運行幾回,有時候會吃飯,有時候會睡覺,好比這樣:

1$ go run x.go
2Mom call you eating
3$ go run x.go
4Time to sleep
5$ go run x.go
6Time to sleep

select很簡單但功能很強大,它讓golang的併發功能變的更強大。這篇文章寫的囉嗦了點,重點是爲下一篇文章作鋪墊,下一篇咱們將介紹下select的高級用法。

select的應用場景不少,讓我總結一下,放在下一篇文章中吧。

 

原創:https://mp.weixin.qq.com/s/ACh-TGlPo72r4e6pbh52vg

併發系列文章推薦

相關文章
相關標籤/搜索