一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Golang - Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

2022-01-19 00:41kuteng Golang

本文主要介紹了Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

簡介:介紹生產(chǎn)者消費者模型,及go簡單實現(xiàn)的demo。

一、生產(chǎn)者消費者模型

生產(chǎn)者消費者模型:某個模塊(函數(shù)等〉負責產(chǎn)生數(shù)據(jù),這些數(shù)據(jù)由另一個模塊來負責處理(此處的模塊是廣義的,可以是類、函數(shù)、協(xié)程、線程、進程等)。產(chǎn)生數(shù)據(jù)的模塊,就形象地稱為生產(chǎn)者;而處理數(shù)據(jù)的模塊,就稱為消費者。
單單抽象出生產(chǎn)者和消費者,還夠不上是生產(chǎn)者消費者模型。該模式還需要有一個緩沖區(qū)處于生產(chǎn)者和消費者之間,作為一個中介。生產(chǎn)者把數(shù)據(jù)放入緩沖區(qū),而消費者從緩沖區(qū)取出數(shù)據(jù)。大概的結構如下圖。

Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

假設你要寄一件快遞,大致過程如下。.
1.把快遞封好——相當于生產(chǎn)者制造數(shù)據(jù)。
2.把快遞交給快遞中心——相當于生產(chǎn)者把數(shù)據(jù)放入緩沖區(qū)。
3.郵遞員把快遞從快遞中心取出——相當于消費者把數(shù)據(jù)取出緩沖區(qū)。

這么看,有了緩沖區(qū)就有了以下好處:
解耦:降低消費者和生產(chǎn)者之間的耦合度。有了快遞中心,就不必直接把快遞交給郵寄員,郵寄快遞的人不對郵寄員產(chǎn)生任何依賴,如果某一個天郵寄員換人了,對于郵寄快遞的人也沒有影響。假設生產(chǎn)者和消費者分別是兩個類。如果讓生產(chǎn)者直接調(diào)用消費者的某個方法,那么生產(chǎn)者對于消費者就會產(chǎn)生依賴(也就是耦合)。將來如果消費者的代碼發(fā)生變化,可能會真接影響到生產(chǎn)者。而如果兩者都依賴于某個緩沖區(qū),兩者之間不直接依賴,耦合度也就相應降低了。
并發(fā):生產(chǎn)者消費者數(shù)量不對等,依然能夠保持正常通信。由于函數(shù)調(diào)用是同步的(或者叫阻塞的),在消費者的方法沒有返回之前,生產(chǎn)者只好一直等在那邊。萬一消費者處理數(shù)據(jù)很慢,生產(chǎn)者只能等著浪費時間。使用了生產(chǎn)者消費者模式之后,生產(chǎn)者和消費者可以是兩個獨立的并發(fā)主體。生產(chǎn)者把制造出來的數(shù)據(jù)往緩沖區(qū)一丟,就可以再去生產(chǎn)下一個數(shù)據(jù)。基本上不用依賴消費者的處理速度。郵寄快遞的人直接把快遞扔個快遞中心之后就不用管了。
緩存:生產(chǎn)者消費者速度不匹配,暫存數(shù)據(jù)。如果郵寄快遞的人一次要郵寄多個快遞,那么郵寄員無法郵寄,就可以把其他的快遞暫存在快遞中心。也就是生產(chǎn)者短時間內(nèi)生產(chǎn)數(shù)據(jù)過快,消費者來不及消費,未處理的數(shù)據(jù)可以暫時存在緩沖區(qū)中。

 

二、Go語言實現(xiàn)

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

1、無緩沖channel

示例代碼一實現(xiàn)如下

package main

import "fmt"

func producer(out chan <- int) {
  for i:=0; i<10; i++{
      data := i*i
      fmt.Println("生產(chǎn)者生產(chǎn)數(shù)據(jù):", data)
      out <- data  // 緩沖區(qū)寫入數(shù)據(jù)
  }
  close(out)  //寫完關閉管道
}


func consumer(in <- chan int){
      // 同樣讀取管道
  //for{
  //    val, ok := <- in
  //    if ok {
  //        fmt.Println("消費者拿到數(shù)據(jù):", data)
  //    }else{
  //        fmt.Println("無數(shù)據(jù)")
  //        break
  //    }
  //}

  // 無需同步機制,先做后做
  // 沒有數(shù)據(jù)就阻塞等
  for data := range in {
      fmt.Println("消費者得到數(shù)據(jù):", data)
  }

}


func main(){
  // 傳參的時候顯式類型像隱式類型轉(zhuǎn)換,雙向管道向單向管道轉(zhuǎn)換
  ch := make(chan int)  //無緩沖channel
  go producer(ch)  // 子go程作為生產(chǎn)者
  consumer(ch)  // 主go程作為消費者
}

這里使用無緩沖channel,生產(chǎn)者生產(chǎn)一次數(shù)據(jù)放入channel,然后消費者從channel讀取數(shù)據(jù),如果沒有只能等待,也就是阻塞,直到管道被關閉。所以宏觀是生產(chǎn)者消費者同步執(zhí)行。
另外:這里是只而外開辟一個go程執(zhí)行生產(chǎn)者,主go程執(zhí)行消費者,如果也是用一個新的go程執(zhí)行消費者,就需要阻塞main函數(shù)中的go程,否則不等待消費者和生產(chǎn)者執(zhí)行完畢,主go程退出,程序直接結束,如示例代碼三。

生產(chǎn)者每一次生產(chǎn),消費者也只能拿到一次數(shù)據(jù),緩沖區(qū)作用不大。結果如下:

Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

2、有緩沖channel

示例代碼二如下

package main

import "fmt"

func producer(out chan <- int) {
  for i:=0; i<10; i++{
      data := i*i
      fmt.Println("生產(chǎn)者生產(chǎn)數(shù)據(jù):", data)
      out <- data  // 緩沖區(qū)寫入數(shù)據(jù)
  }
  close(out)  //寫完關閉管道
}


func consumer(in <- chan int){

  // 無需同步機制,先做后做
  // 沒有數(shù)據(jù)就阻塞等
  for data := range in {
      fmt.Println("消費者得到數(shù)據(jù):", data)
  }

}


func main(){
  // 傳參的時候顯式類型像隱式類型轉(zhuǎn)換,雙向管道向單向管道轉(zhuǎn)換
  ch := make(chan int, 5)  // 添加緩沖區(qū),5

  go producer(ch)  // 子go程作為生產(chǎn)者
  consumer(ch)  // 主go程作為消費者
}

有緩沖channel,只修改ch := make(chan int, 5) // 添加緩沖一句,只要緩沖區(qū)不滿,生產(chǎn)者可以持續(xù)向緩沖區(qū)channel放入數(shù)據(jù),只要緩沖區(qū)不為空,消費者可以持續(xù)從channel讀取數(shù)據(jù)。就有了異步,并發(fā)的特性。
結果如下:

Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

這里之所以終端生產(chǎn)者連續(xù)打印了大于緩沖區(qū)容量的數(shù)據(jù),是因為終端打印屬于系統(tǒng)調(diào)用也是有延遲的,IO操作的時候,生產(chǎn)者同時向管道寫入,請求打印,管道的寫入讀取與終端輸出打印速度不匹配。

 

三、實際應用

實際應用中,同時訪問同一個公共區(qū)域,同時進行不同的操作。都可以劃分為生產(chǎn)者消費者模型,比如訂單系統(tǒng)。
很多用戶的訂單下達之后,放入緩沖區(qū)或者隊列中,然后系統(tǒng)從緩沖區(qū)中去讀來真正處理。系統(tǒng)不必開辟多個線程來對應處理多個訂單,減少系統(tǒng)并發(fā)的負擔。通過生產(chǎn)者消費者模式,將訂單系統(tǒng)與倉庫管理系統(tǒng)隔離開,且用戶可以隨時下單(生產(chǎn)數(shù)據(jù))。如果訂單系統(tǒng)直接調(diào)用倉庫系統(tǒng),那么用戶單擊下訂單按鈕后,要等到倉庫系統(tǒng)的結果返回。這樣速度會很慢。
也就是:用戶變成了生產(chǎn)者,處理訂單管理系統(tǒng)變成了消費者。

代碼示例三如下

package main

import (
  "fmt"
  "time"
)


// 模擬訂單對象
type OrderInfo struct {
  id int
}


// 生產(chǎn)訂單--生產(chǎn)者
func producerOrder(out chan <- OrderInfo)  {
  // 業(yè)務生成訂單
  for i:=0; i<10; i++{
      order := OrderInfo{id: i+1}
      fmt.Println("生成訂單,訂單ID為:", order.id)
      out <- order // 寫入channel
  }
  // 如果不關閉,消費者就會一直阻塞,等待讀
  close(out)  // 訂單生成完畢,關閉channel
}


// 處理訂單--消費者
func consumerOrder(in <- chan OrderInfo)  {
  // 從channel讀取訂單,并處理
  for order := range in{
      fmt.Println("讀取訂單,訂單ID為:", order.id)
  }
}

func main()  {
  ch := make(chan OrderInfo, 5)
  go producerOrder(ch)
  go consumerOrder(ch)
  time.Sleep(time.Second * 2)
}

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

Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型

到此這篇關于Go語言實現(xiàn)一個簡單生產(chǎn)者消費者模型的文章就介紹到這了,更多相關Go語言生產(chǎn)者消費者 內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.topgoer.cn/blog-171.html

延伸 · 閱讀

精彩推薦
  • Golanggo日志系統(tǒng)logrus顯示文件和行號的操作

    go日志系統(tǒng)logrus顯示文件和行號的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
  • Golanggolang如何使用struct的tag屬性的詳細介紹

    golang如何使用struct的tag屬性的詳細介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細介紹,從例子說起,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關于golang的httpserver優(yōu)雅重啟的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,...

    helight2992020-05-14
  • GolangGolang中Bit數(shù)組的實現(xiàn)方式

    Golang中Bit數(shù)組的實現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧...

    天易獨尊11682021-06-09
  • GolangGolang通脈之數(shù)據(jù)類型詳情

    Golang通脈之數(shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之數(shù)據(jù)類型,在編程語言中標識符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標識符允許由...

    4272021-11-24
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
主站蜘蛛池模板: 我与白丝同桌的故事h文 | 亚洲国产精品福利片在线观看 | 国产好痛疼轻点好爽的视频 | 国产成人夜色影视视频 | 欧美三级小说 | 精品国产品香蕉在线观看75 | 99久久99热久久精品免 | 国产在线视频色综合 | 国色天香 社区视频 | 日本片免费观看一区二区 | 国产一级一级一级成人毛片 | 91在线精品国产 | 精品国产乱码久久久久久软件 | 亚洲欧美日韩中文字幕网址 | 成人欧美一区二区三区 | 丰满肥臀风间由美357在线 | 亚洲男人网| 亚洲 欧美 国产 综合 在线 | 成年人免费观看视频网站 | 四虎在线精品免费高清在线 | 息与子中文字幕在线 | 亚洲 小说 欧美 激情 另类 | 亚洲精品丝袜在线一区波多野结衣 | 男男playh片在线观看 | ova催眠性指导5最新在线 | 四虎现在的网址入口2022 | 国产自在线观看 | 婷婷久久综合 | 粉嫩尤物在线456 | 国产成人在线视频 | 好男人资源免费播放 | 免费91麻豆精品国产自产在线观看 | 国产专区日韩精品欧美色 | 午夜理论片日本中文在线 | 久久久精品国产免费A片胖妇女 | 色中文字幕 | 国产自在自拍 | 2021国产麻豆剧传媒剧情动漫 | 无人区1免费完整观看 | 精品午夜寂寞影院在线观看 | 兽皇日本|