写点什么

Golang 高并发:生产者消费者模型

用户头像
Regan Yue
关注
发布于: 2021 年 08 月 23 日
Golang高并发:生产者消费者模型

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("消费全部完毕!")
复制代码


就能够只读取管道里面的商品。

发布于: 2021 年 08 月 23 日阅读数: 3
用户头像

Regan Yue

关注

还未添加个人签名 2020.08.12 加入

还未添加个人简介

评论

发布
暂无评论
Golang高并发:生产者消费者模型