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

简介: 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("消费全部完毕!")

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

目录
相关文章
|
4月前
|
存储 NoSQL Redis
单线程模型想象不到的高并发能力、多路复用是效率杠杆
单线程模型想象不到的高并发能力、多路复用是效率杠杆
|
11月前
|
存储 监控 Linux
Golang 语言的 goroutine 调度器模型 GPM
Golang 语言的 goroutine 调度器模型 GPM
55 0
|
4月前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第2天】Go语言的并发编程基于CSP模型,强调通过通信共享内存。核心概念是goroutines(轻量级线程)和channels(用于goroutines间安全数据传输)。常见问题包括数据竞争、死锁和goroutine管理。避免策略包括使用同步原语、复用channel和控制并发。示例展示了如何使用channel和`sync.WaitGroup`避免死锁。理解并发原则和正确应用CSP模型是编写高效安全并发程序的关键。
102 7
|
4月前
|
安全 Go 开发者
Golang深入浅出之-Go语言中的CSP模型:深入理解并发哲学
【5月更文挑战第1天】Go语言基于CSP理论,借助goroutines和channels实现独特的并发模型。Goroutine是轻量级线程,通过`go`关键字启动,而channels提供安全的通信机制。文章讨论了数据竞争、死锁和goroutine泄漏等问题及其避免方法,并提供了一个生产者消费者模型的代码示例。理解CSP和妥善处理并发问题对于编写高效、可靠的Go程序至关重要。
95 2
|
4月前
|
监控 编译器 Linux
golang面试:golang的GPM调度模型(七)
golang面试:golang的GPM调度模型(七)
51 1
|
存储 安全 算法
【Java|多线程与高并发】阻塞队列以及生产者-消费者模型
阻塞队列(BlockingQueue)常用于多线程编程中,可以实现线程之间的同步和协作。它可以用来解决生产者-消费者问题,其中生产者线程将元素插入队列,消费者线程从队列中获取元素,它们之间通过阻塞队列进行协调。
|
监控 网络协议 Linux
【计算机网络】高并发业务必备的Linux网络IO模型
【计算机网络】高并发业务必备的Linux网络IO模型
【计算机网络】高并发业务必备的Linux网络IO模型
|
Go 数据安全/隐私保护
golang mutex两加两解助你实现高并发控制
golang mutex两加两解助你实现高并发控制
|
Java
高并发编程-线程生产者消费者的综合示例
高并发编程-线程生产者消费者的综合示例
72 0