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

517 阅读4分钟

我们本篇博文主要通过几个例子来介绍生产者消费者模型。

案例一

生产者协程

// 生产商品
go func() {
    for {
        productId := strconv.Itoa(time.Now().Nanosecond())
        chanShop <- "商品" + productId
        fmt.Println("生产了商品", productId)
        time.Sleep(time.Second)
        }
   }()

消费者协程

// 消费商品
go func() {
    for {
        product := <- chanShop
        fmt.Println("消费了商品", product)
        time.Sleep(time.Second)
        }
    }()

主程序任务等待

// 主程序
for {
    time.Sleep(time.Second)
}

完整案例

// 生产者消费者模型之源源不断的生产消费,生产消费
package main
​
import (
    "fmt"
    "strconv"
    "time"
)
​
func main() {
    chanShop := make(chan string)
    // 生产商品
    go func() {
        for {
            productId := strconv.Itoa(time.Now().Nanosecond())
            chanShop <- "商品" + productId
            fmt.Println("生产了商品", productId)
            time.Sleep(time.Second)
          }
     }()
​
    // 消费商品
    go func() {
        for {
            product := <- chanShop
            fmt.Println("消费了商品", product)
​
            time.Sleep(time.Second)
            }
   }()
​
    // 主程序
    for {
        time.Sleep(time.Second)
    }
}

案例二

此案例引入一个”物流“的概念,完成对他的生产消费。

chan定义

// 定义中转物流仓库,定义存储100个上商品
chanStorage := make(chan string100)
// 定义消费渠道,由消费者进行消费
chanSell := make(chan string100)

producer生产者

// 制造商品,producer
go func() {
    for i := 0; i < 10; i++ {
        product := strconv.Itoa(time.Now().Nanosecond())
        chanStorage <- "商品:" + product
        fmt.Println("生产了商品", product)
    }
    close(chanStorage)
}()

物流中转

// 进行中转托运
go func() {
    for p := range chanStorage{
        chanSell <- p
        fmt.Println("完成了中转托运", p)
    }
    fmt.Println("商品转运完成! 商店关闭!")
    close(chanSell)
}()

消费者 comsumer

// 进行售卖商品, comsumer
go func() {
    for sellerP := range chanSell{
    fmt.Println("消费了商品", sellerP)
    fmt.Println()
    }
    fmt.Println("商品已经全部消费完成!")
}()

主协程等待

// 主流程
for {
    time.Sleep(time.Second)
}

完整案例

// 生产者消费者模型之中转物流
package main
​
import (
    "fmt"
    "strconv"
    "time"
)
​
func main() {
    // 定义中转物流仓库,定义存储100个上商品
    chanStorage := make(chan string100)
    // 定义消费渠道,由消费者进行消费
    chanSell := make(chan string100)
​
    // 制造商品,producer
    go func() {
        for i := 0; i < 10; i++ {
            product := strconv.Itoa(time.Now().Nanosecond())
            chanStorage <- "商品:" + product
            fmt.Println("生产了商品", product)
        }
        close(chanStorage)
    }()
​
    // 进行中转托运
    go func() {
        for p := range chanStorage{
            chanSell <- p
            fmt.Println("完成了中转托运", p)
        }
        fmt.Println("商品转运完成! 商店关闭!")
        close(chanSell)
    }()
​
    // 进行售卖商品, comsumer
    go func() {
    for sellerP := range chanSell{
        fmt.Println("消费了商品", sellerP)
        fmt.Println()
        }
        fmt.Println("商品已经全部消费完成!")
    }()
​
    // 主流程
    for {
        time.Sleep(time.Second)
    }
}

抽离函数式进阶

// 生产者消费者模型之中转物流
package main
​
import (
    "fmt"
    "strconv"
    "time"
)
​
// 定义producer
func producer(chanStorage chan string) {
    for i := 0; i < 10; i++ {
        product := strconv.Itoa(time.Now().Nanosecond())
        chanStorage <- "商品:" + product
        fmt.Println("生产了商品", product)
    }
    close(chanStorage)
}
​
// 定义中转效果
func logisic(chanStorage, chanSell chan string) {
    for p := range chanStorage{
        chanSell <- p
        fmt.Println("完成了中转托运", p)
    }
    fmt.Println("商品转运完成! 商店关闭!")
    close(chanSell)
}
​
// 定义消费者
func consumer(chanSell chan string) {
    for sellerP := range chanSell{
        fmt.Println("消费了商品", sellerP)
        fmt.Println()
    }
    fmt.Println("商品已经全部消费完成!")
}
​
func main() {
    // 定义中转物流仓库,定义存储100个上商品
    chanStorage := make(chan string100)
    // 定义消费渠道,由消费者进行消费
    chanSell := make(chan string100)
​
    // 制造商品,producer
    go producer(chanStorage)
​
    // 进行中转托运
    go logisic(chanStorage, chanSell)
​
    // 进行售卖商品, comsumer
    go consumer(chanSell)
​
    // 主流程
    for {
        time.Sleep(time.Second)
    }
}

结果展示

完成了中转托运 商品:524589000
消费了商品 商品:524589000
​
生产了商品 524589000
生产了商品 525884000
生产了商品 525890000
生产了商品 525892000
生产了商品 525893000
生产了商品 525894000
生产了商品 525895000
生产了商品 525896000
生产了商品 525897000
生产了商品 525898000
完成了中转托运 商品:525884000
完成了中转托运 商品:525890000
完成了中转托运 商品:525892000
完成了中转托运 商品:525893000
完成了中转托运 商品:525894000
完成了中转托运 商品:525895000
完成了中转托运 商品:525896000
完成了中转托运 商品:525897000
完成了中转托运 商品:525898000
商品转运完成! 商店关闭!
消费了商品 商品:525884000
消费了商品 商品:525890000
消费了商品 商品:525892000
消费了商品 商品:525893000
消费了商品 商品:525894000
消费了商品 商品:525895000

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