一次场景模拟/go实现

    无论是生产者还是消费者各自是独立的,但彼此又相关联。今日我用go语言模拟一个并发的生产和消费场景。

    背景是这样的:

    ```

    有一个生产饮料的工厂, 工厂里有2个生产机器, 每生产一个产品要花费1h,生产的产品会自动放到仓库中,仓库可容纳5个这样的产品,有3个员工,他们每一个人需要花费0.8h 将1个产品搬运到小区中地摊上等待售卖,每隔1.5h会有一个顾客来到摊子上等待购买这种产品(这种商品是通过抢购获取,与来得早晚无关),如果等待了2h依然没买到就会离开。每一天,如果工厂里的产品材料耗尽,那么机器将停运,再员工要将所有商品售出后,地摊也会被回收,工厂进入停业状态。

    ```

机器和员工之间的工作是独立的,员工的工作依赖机器生产的产品,而顾客依赖地摊上的产品,使用一个协程代表一个实体(机器/员工/顾客),彼此间使用channel通讯,模拟依赖关系。

 

程序如下:

package main

import (
    "fmt"
    "sync"
    "time"
)

/*------------------ 场景实现*/

func main() {
    wg := sync.WaitGroup{}
    //设置工厂仓库容量
    cl := make(chan int, 5)
    //设置工厂员工令牌
    py := make(chan struct{}, 3)
    //设置工厂机器令牌
    jq := make(chan struct{}, 2)
    //设置容纳原材料的容器(2个容器)
    rq := make(chan int, 2)
    //设置小区地摊在售产品
    yl := make(chan int)
    //停工信号
    ab := make(chan struct{})
    //停业信号
    st := make(chan struct{})
    //工厂是否停工
    aborted := func() bool {
        select {
        case <- ab:
            return true;
        default:
            return false
        }
    }
    //工厂是否停业
    factoryStop := func() bool {
        select {
        case <- st:
            return true
        default:
            return false
        }
    }
    //3个员工开始上班
    for i := 0; i < 3; i++ {
        wg.Add(1)
        py <- struct{}{}
        go func(id int, cl <-chan int) {
            defer wg.Done();
            for {
                var x int
                var timeout bool
                //可用劳动力-1
                <- py
                //员工只有在在机器停工后, 且售卖完仓库的产品后才能停工
                if  len(cl) == 0 && len(jq) == 2 && aborted() {
                    fmt.Printf("工人:`%d` 停工...\n", id)
                    return
                }
                //延时轮询, 避免死锁
                select {
                case x = <-cl:
                case <-time.After(800 * time.Millisecond):
                    py <- struct{}{}
                    timeout = true
                }
                if timeout {
                    continue
                }
                fmt.Printf("工人:`%d` %d-搬运中...\n", id, x)
                time.Sleep(500*time.Millisecond)    //搬运耗时: 0.5h
                yl <- x                             //产品售卖中
                time.Sleep(300*time.Millisecond)    //返回: 0.3h
                //补充劳动力
                fmt.Printf("工人:`%d` 回厂了...\n", id)
                //可用劳动力+1
                py <- struct{}{}
            }
        }(i, cl)
    }
    //2台机器开始工作
    for i := 0; i < 2; i++ {
        wg.Add(1)
        jq <- struct{}{}
        go func (id int, in chan<- int, out <-chan int) {
            defer wg.Done()
            for {
                var p int
                var timeout bool
                //可用机器-1
                <- jq
                //即使停机, 机器也需要将容器中的原材料给消耗完毕
                if len(out) == 0 && aborted() {
                    fmt.Println("机器停工了...")
                    return
                }
                //延时轮询, 避免死锁
                select {
                case p = <-out:
                case <-time.After(time.Second):
                    timeout = true
                    jq <- struct{}{}
                }
                if timeout {
                    continue
                }
                fmt.Printf("jq:`%d` %d-生产中...\n", id, p)
                time.Sleep(time.Second)     //耗时1h
                //产品入库
                in <-p
                //可用机器+1
                jq <- struct{}{}
            }
            //defer wg.Done()
        }(i, cl, rq)
    }
    go func(yl <-chan int) {
        //不考虑有多少顾客排队, 也不考虑排队顺序
        for {
            //地摊还在不?
            if factoryStop() {
                break
            }
            go func(yl <-chan int) {
                //抢购商品
                select {
                //等待
                case i := <-yl:
                    fmt.Printf("luck, 抢到了 %d\n", i)
                //地摊收回, 等待者离开
                case <-st:
                    fmt.Println("今天卖完了... 离开吧")
                //等了2h后, 离开
                case <-time.After(2*time.Second):
                    fmt.Println("不耐烦地走了")
                }
            }(yl)
            fmt.Println("一个顾客加入抢购...")
            time.Sleep(1500*time.Millisecond)
        }
    }(yl)

    //工厂开工
    number := 10    //原材料数量
    for i := 0; i < number; i++ {
        //往容器中装入原材料
        rq <- i
    }
    //停工
    close(ab)
    //等待
    wg.Wait()
    //停业
    close(st)
    close(jq)   //关闭机器
    close(cl)   //清理库存
    close(py)   //员工下班
    close(rq)   //清理容器
    //工厂关门
    fmt.Println("工厂停业")
}

上面仅实现了提供差不多能满足市场需要,可以通过调整参数模拟出"供不应求“的场景,再或者调整员工的销售规则(并且允许囤货等)模拟“供大于求”的场景。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值