Golang高并發:生産者消費者模型
我們本篇博文主要通過幾個例子來介紹生産者消費者模型。
案例1
下面看看第一個例子中的生産者協程。
//生産者協程
go func() {
for {
product := strconv.Itoa(time.Now().Nanosecond())
chanShop <- "商品" + product
fmt.Println("生産了商品",product)
time.Sleep(1000 * time.Millisecond)
}
}()
生産者協程就是源源不斷的生産,将時間轉化為字元串,然後源源不斷的産生産品字元串。此處用到了
strconv.Itoa()
,是将整型轉換為字元串類型。
time.Now()
是目前的時間,而使用Nanosecond()是将其轉換為納秒。然後将得到的産品序列号字元串放入視訊管道,然後輸出生産了什麼産品,然後睡一秒,然後接着生産。
至于消費者協程,我相信你已經猜到了是什麼了,我們也來看一看吧。
//消費者協程
go func() {
for{
product := <-chanShop
fmt.Println("消費了産品",product)
time.Sleep(time.Second)
}
}()
每次從商品管道取一個産品,然後輸出消費了什麼産品,然後睡一秒,然後繼續消費。
再來看看這個案例的主協程
//主協程
for {
time.Sleep(time.Second)
}
運作結果是
消費了産品 商品607861100
生産了商品 607861100
生産了商品 607929500
消費了産品 商品607929500
生産了商品 608013000
消費了産品 商品608013000
生産了商品 608018400
消費了産品 商品608018400
沒錯,源源不斷的生産消費、生産消費。
案例2
我們再來看看第二個案例,這個案例,我們引入了”物流“的概念。
先上主函數給各位讀者老爺看看吧:
func main() {
chanStorage := make(chan string ,100)
chanShop := make(chan string, 100)
go producer(chanStorage)
go logistics(chanStorage,chanShop)
go consumer(chanShop)
for {
time.Sleep(time.Second)
}
}
主要是建立商店和物流兩條管道,然後建立生産者、消費者、物流三條協程,然後主協程一直不
go die
。
然後先來看看生産者協程
func producer(chanStorage chan string) {
for i:=0;i<10;i++{
product := strconv.Itoa(time.Now().Nanosecond())
chanStorage <- "産品"+product
fmt.Println("生産了産品",product)
time.Sleep(time.Second)
}
close(chanStorage)
}
和第一個案例一樣,不過我們隻生産10個産品放入倉庫,然後關閉了倉庫。
然後看看物流協程是幹了些什麼:
func logistics(chanStroge,chanShop chan string) {
for p:= range chanStroge{
fmt.Println("物流完成轉運",p)
chanShop <- p
}
fmt.Println("商品轉運完畢!")
}
源源不斷掃描倉庫,拿出商品然後将商品轉運到商店。當生産者關閉倉庫後,物流也停止轉運了。
消費者不斷在消費,然後看看消費者:
func consumer(chanShop chan string) {
for{
product := <-chanShop
fmt.Println("消費了産品",product)
}
}
等來一件商品,就賣出去。
然後看看運作結果
生産了産品 605763200物流完成轉運 産品605763200消費了産品 産品605763200生産了産品 605826700物流完成轉運 産品605826700消費了産品 産品605826700生産了産品 619889800物流完成轉運 産品619889800消費了産品 産品619889800生産了産品 619906200物流完成轉運 産品619906200消費了産品 産品619906200生産了産品 627948700物流完成轉運 産品627948700消費了産品 産品627948700
我們可以看到,生産、轉運、消費幾乎是同時的。
因為我們當物流公司停止運物資時,商店也要關門,是以在物流協程内加入:
close(chanShop) fmt.Println("商品轉運完畢!商店已歇業!")
然後繼續把消費者的for循環替換成
for product := range chanShop{ //product := <-chanShop fmt.Println("消費了産品",product) fmt.Println() } fmt.Println("消費全部完畢!")
就能夠隻讀取管道裡面的商品。