成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

生產者消費者模型及 Golang 實現

開發 后端
本文介紹了生產者消費者模型,和 go 實現的簡單 demo。

 [[441586]]

本文介紹了生產者消費者模型,和 go 實現的簡單 demo。

一、生產者消費者模型

生產者消費者模型:某個模塊(函數等〉負責產生數據,這些數據由另一個模塊來負責處理(此處的模塊是廣義的,可以是類、函數、協程、線程、進程等)。產生數據的模塊,就形象地稱為生產者;而處理數據的模塊,就稱為消費者。

單單抽象出生產者和消費者,還夠不上是生產者消費者模型。該模式還需要有一個緩沖區處于生產者和消費者之間,作為一個中介。生產者把數據放入緩沖區,而消費者從緩沖區取出數據。大概的結構如下圖。圖片

假設你要寄一件快遞,大致過程如下:

1.把快遞封好——相當于生產者制造數據。

2.把快遞交給快遞中心——相當于生產者把數據放入緩沖區。

3.郵遞員把快遞從快遞中心取出——相當于消費者把數據取出緩沖區。

這么看,有了緩沖區就有了以下好處:

解耦:降低消費者和生產者之間的耦合度。有了快遞中心,就不必直接把快遞交給郵寄員,郵寄快遞的人不對郵寄員產生任何依賴,如果某一個天郵寄員換人了,對于郵寄快遞的人也沒有影響。假設生產者和消費者分別是兩個類。如果讓生產者直接調用消費者的某個方法,那么生產者對于消費者就會產生依賴(也就是耦合)。將來如果消費者的代碼發生變化,可能會真接影響到生產者。而如果兩者都依賴于某個緩沖區,兩者之間不直接依賴,耦合度也就相應降低了。

并發:生產者消費者數量不對等,依然能夠保持正常通信。由于函數調用是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產者只好一直等在那邊。萬一消費者處理數據很慢,生產者只能等著浪費時間。使用了生產者消費者模式之后,生產者和消費者可以是兩個獨立的并發主體。生產者把制造出來的數據往緩沖區一丟,就可以再去生產下一個數據?;旧喜挥靡蕾囅M者的處理速度。郵寄快遞的人直接把快遞扔個快遞中心之后就不用管了。

緩存:生產者消費者速度不匹配,暫存數據。如果郵寄快遞的人一次要郵寄多個快遞,那么郵寄員無法郵寄,就可以把其他的快遞暫存在快遞中心。也就是生產者短時間內生產數據過快,消費者來不及消費,未處理的數據可以暫時存在緩沖區中。

二、Go語言實現

單向channel最典型的應用是“生產者消費者模型”。channel又分為有緩沖和無緩沖channel。channel中參數傳遞的時候,是作為引用傳遞。

1、無緩沖channel

示例代碼一實現如下 

  1. package main  
  2. import "fmt"  
  3. func producer(out chan <- int) {  
  4.  for i:=0; i<10; i++{  
  5.   data :i*i 
  6.   fmt.Println("生產者生產數據:", data)  
  7.   out <- data  // 緩沖區寫入數據  
  8.  }  
  9.  close(out)  //寫完關閉管道  
  10.   
  11. func consumer(in <- chan int){  
  12.         // 同樣讀取管道  
  13.  //for{  
  14.  // val, ok :<- in  
  15.  // if ok {  
  16.  //  fmt.Println("消費者拿到數據:", data)  
  17.  // }else{  
  18.  //  fmt.Println("無數據")  
  19.  //  break  
  20.  // }  
  21.  //}    
  22.  // 無需同步機制,先做后做  
  23.  // 沒有數據就阻塞等  
  24.  for data :range in {  
  25.   fmt.Println("消費者得到數據:", data)  
  26.  }  
  27.  
  28. func main(){  
  29.  // 傳參的時候顯式類型像隱式類型轉換,雙向管道向單向管道轉換  
  30.  ch :make(chan int)  //無緩沖channel  
  31.  go producer(ch)  // 子go程作為生產者  
  32.  consumer(ch)  // 主go程作為消費者 
  33.  

這里使用無緩沖channel,生產者生產一次數據放入channel,然后消費者從channel讀取數據,如果沒有只能等待,也就是阻塞,直到管道被關閉。所以宏觀是生產者消費者同步執行。

另外:這里是只而外開辟一個go程執行生產者,主go程執行消費者,如果也是用一個新的go程執行消費者,就需要阻塞main函數中的go程,否則不等待消費者和生產者執行完畢,主go程退出,程序直接結束,如示例代碼三。

生產者每一次生產,消費者也只能拿到一次數據,緩沖區作用不大。結果如下:

2、有緩沖channel

示例代碼二如下 

  1. package main  
  2. import "fmt"  
  3. func producer(out chan <- int) {  
  4.  for i:=0; i<10; i++{  
  5.   data :i*i  
  6.   fmt.Println("生產者生產數據:", data)  
  7.   out <- data  // 緩沖區寫入數據  
  8.  }  
  9.  close(out)  //寫完關閉管道  
  10.   
  11. func consumer(in <- chan int){  
  12.  // 無需同步機制,先做后做  
  13.  // 沒有數據就阻塞等  
  14.  for data :range in {  
  15.   fmt.Println("消費者得到數據:", data)  
  16.  }  
  17.  
  18. func main(){  
  19.  // 傳參的時候顯式類型像隱式類型轉換,雙向管道向單向管道轉換  
  20.  ch :make(chan int, 5)  // 添加緩沖區,5  
  21.  go producer(ch)  // 子go程作為生產者  
  22.  consumer(ch)  // 主go程作為消費者  

有緩沖channel,只修改ch := make(chan int, 5) // 添加緩沖一句,只要緩沖區不滿,生產者可以持續向緩沖區channel放入數據,只要緩沖區不為空,消費者可以持續從channel讀取數據。

就有了異步,并發的特性。結果如下:圖片

這里之所以終端生產者連續打印了大于緩沖區容量的數據,是因為終端打印屬于系統調用也是有延遲的,IO操作的時候,生產者同時向管道寫入,請求打印,管道的寫入讀取與終端輸出打印速度不匹配。

三、實際應用

實際應用中,同時訪問同一個公共區域,同時進行不同的操作。都可以劃分為生產者消費者模型,比如訂單系統。很多用戶的訂單下達之后,放入緩沖區或者隊列中,然后系統從緩沖區中去讀來真正處理。

系統不必開辟多個線程來對應處理多個訂單,減少系統并發的負擔。通過生產者消費者模式,將訂單系統與倉庫管理系統隔離開,且用戶可以隨時下單(生產數據)。如果訂單系統直接調用倉庫系統,那么用戶單擊下訂單按鈕后,要等到倉庫系統的結果返回。這樣速度會很慢。

也就是:用戶變成了生產者,處理訂單管理系統變成了消費者。

代碼示例三如下 

  1. package main  
  2. import (  
  3.  "fmt"  
  4.  "time"  
  5.  
  6. // 模擬訂單對象  
  7. type OrderInfo struct {  
  8.  id int  
  9. // 生產訂單--生產者  
  10. func producerOrder(out chan <- OrderInfo)  {  
  11.  // 業務生成訂單  
  12.  for i:=0; i<10; i++{  
  13.   order :OrderInfo{id: i+1}  
  14.   fmt.Println("生成訂單,訂單ID為:", order.id)  
  15.   out <- order // 寫入channel  
  16.  }  
  17.  // 如果不關閉,消費者就會一直阻塞,等待讀  
  18.  close(out)  // 訂單生成完畢,關閉channel  
  19.  
  20. // 處理訂單--消費者  
  21. func consumerOrder(in <- chan OrderInfo)  {  
  22.  // 從channel讀取訂單,并處理  
  23.  for order :range in{  
  24.   fmt.Println("讀取訂單,訂單ID為:", order.id)  
  25.  }  
  26.  
  27. func main()  {  
  28.  ch :make(chan OrderInfo, 5)  
  29.  go producerOrder(ch)  
  30.  go consumerOrder(ch)  
  31.  time.Sleep(time.Second * 2)  

這里如上面邏輯類似,不同的是用一個,OrderInfo結構體模擬訂單作為業務處理對象。主線程使用time.Sleep(time.Second * 2)阻塞,否則,程序立即停止。結果如下:

 

 

責任編輯:龐桂玉 來源: 馬哥Linux運維
相關推薦

2015-08-26 09:39:30

java消費者

2009-08-13 13:14:31

C#生產者和消費者

2024-10-11 09:27:52

2017-05-16 12:30:21

Python多線程生產者消費者模式

2012-02-14 12:31:27

Java

2024-03-14 11:58:43

2024-08-27 10:19:31

2021-08-31 10:26:24

存儲

2020-09-14 08:45:58

多線程模型面試

2021-04-20 08:32:51

消息MQ隊列

2021-12-28 12:01:59

Kafka 消費者機制

2023-06-01 08:08:38

kafka消費者分區策略

2015-06-15 11:29:34

數據中心綠色數據中心

2022-07-07 09:00:49

RocketMQ消費者消息消費

2011-08-05 16:21:24

2011-07-22 16:25:38

CA TechnoloIT消費化

2021-07-08 05:52:34

Kafka架構主從架構

2011-11-15 10:05:29

Kindle Fire平板市場

2021-07-05 06:26:08

生產者kafka架構

2015-08-31 10:45:02

數據
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 337p日本欧洲亚洲大胆 | 一区二区三区小视频 | 国产精品美女久久久久aⅴ国产馆 | 精品视频免费 | 亚洲伊人久久综合 | 中文字幕欧美一区 | 国产99久久精品一区二区永久免费 | 国产在线一区二区三区 | 久久久久久久综合 | 在线精品一区二区三区 | 日本免费网 | 97人人爱 | 亚洲性视频 | 91在线精品一区二区 | 日韩在线一区二区三区 | 亚洲精品久久久 | 91精品国模一区二区三区 | 久久久久久久91 | 在线一区二区三区 | 成年人在线观看 | 91高清视频在线观看 | 日韩精品激情 | 成人一区在线观看 | 精品国产一区二区三区日日嗨 | 久久久久国产精品午夜一区 | 精品久久影院 | 一区二区三区国产好 | 日韩欧美一级精品久久 | 欧美日韩在线电影 | 91av久久久| 国产精品久久久久久久久久久久 | 中文字幕 在线观看 | 男人天堂久久 | 日韩欧美精品一区 | 成年网站在线观看 | 国产福利视频 | 国产一级在线观看 | 国产一区二区三区在线 | 日本午夜精品 | 中文字幕一页二页 | 91精品国产色综合久久不卡98 |