美文网首页
牛奶发酵剂奶酪,设计生产系统

牛奶发酵剂奶酪,设计生产系统

作者: 站在海边看远方 | 来源:发表于2020-11-03 15:23 被阅读0次

题目描述如下:

有一家生产奶酪的厂家,每天需要生产100000份奶酪卖给超市,通过一辆送货车发货,送货车辆每次送100份。
厂家有一个容量为1000份的冷库,用于奶酪保鲜,生产的奶酪需要先存放在冷库,运输车辆从冷库取货。
厂家有三条生产线,分别是牛奶供应生产线,发酵剂制作生产线,奶酪生产线。生产每份奶酪需要2份牛奶和1份发酵剂。
请设计生产系统。

根据以下要求,我们可以考虑这么几个方面

  • 牛奶生产和发酵剂生产作为生产者,奶酪生产作为消费者
  • 奶酪生产作为生产者,货车发车作为消费者
  • 牛奶存储和发酵剂存储以及奶酪存储,使用3个阻塞队列暂存
  • 货车装车从奶酪队列里每取一百次发一次车
  • 一共4个生产者,2个消费者,3个阻塞队列

下面是代码实现

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 生产奶酪
 *
 * @author since
 * @date 2020-11-02 16:04
 **/
public class Cheese {

    /**
     * 每天生产奶酪的总量
     */
    private static final Integer TOTAL_PRODUCTION = 100000;

    /**
     * 牛奶的数量-200000/天
     */
    private static final AtomicInteger MILK_SIZE = new AtomicInteger(0);

    /**
     * 发酵剂的数量-100000/天
     */
    private static final AtomicInteger STARTER_SIZE = new AtomicInteger(0);

    /**
     * 奶酪的数量-100000/天
     */
    private static final AtomicInteger CHEESE_SIZE = new AtomicInteger(0);

    /**
     * 取奶酪的次数
     */
    private static final AtomicInteger CHEESE_TAKE_TIMES = new AtomicInteger(0);


    /**
     * 阻塞队列,用于存放奶酪,生产者是牛奶和发酵剂,消费者是货车发货,每次发100份
     */
    private static final BlockingQueue<Integer> CHEESE_QUEUE = new LinkedBlockingQueue<>(1000);

    /**
     * 阻塞队列,用于存放生产的牛奶,生产者是牛奶,消费者是奶酪生产
     */
    private static final BlockingQueue<Integer> MILK_QUEUE = new LinkedBlockingQueue<>(2);

    /**
     * 阻塞队列,用于存放生产的发酵剂,生产者是发酵剂,消费者是奶酪生产
     */
    private static final BlockingQueue<Integer> STARTER_QUEUE = new LinkedBlockingQueue<>(1);

    /**
     * 奶酪生产线程池
     */
    private static final ThreadPoolExecutor CHEESE_PRODUCER = new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("cheese-producer-%d").build(), (r, executor) -> System.out.println("Cheese Reject Task"));

    /**
     * 发酵剂生产线程池
     */
    private static final ThreadPoolExecutor STARTER_PRODUCER = new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("starter-producer-%d").build(), (r, executor) -> System.out.println("Starter Reject Task"));

    /**
     * 牛奶生产线程池
     */
    private static final ThreadPoolExecutor MILK_PRODUCER = new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("milk-producer-%d").build(), (r, executor) -> System.out.println("Milk Reject Task"));

    /**
     * 货车发货线程池
     */
    private static final ThreadPoolExecutor TRUCKING = new ThreadPoolExecutor(5, 10, 1, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1), new ThreadFactoryBuilder().setNameFormat("trucking-%d").build(), (r, executor) -> System.out.println("Trunking Reject Task"));


    /**
     * 奶酪生产线程
     */
    static class CheeseProducer implements Runnable {

        @Override
        public void run() {
            while (CHEESE_SIZE.get() < TOTAL_PRODUCTION) {
                try {
                    //发酵剂取1
                    STARTER_QUEUE.take();
                    //System.out.println("生产奶酪,发酵剂取1");

                    //牛奶取2
                    MILK_QUEUE.take();
                    MILK_QUEUE.take();

                    //System.out.println("生产奶酪,发酵剂取2");

                    //奶酪生产1
                    CHEESE_QUEUE.put(1);
                    //System.out.println("生产1份奶酪");

                    //生产数量加1
                    int i = CHEESE_SIZE.incrementAndGet();

                    if (CHEESE_SIZE.get() == TOTAL_PRODUCTION) {
                        System.out.println("本日奶酪已生产完,共" + i + "份");
                    }


                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 发酵剂生产线程
     */
    static class StarterProducer implements Runnable {

        @Override
        public void run() {
            while (STARTER_SIZE.get() < TOTAL_PRODUCTION) {
                try {
                    STARTER_QUEUE.put(1);
                    //System.out.println("生产1份发酵剂");
                    //发酵剂+1
                    int i = STARTER_SIZE.incrementAndGet();
                    if (STARTER_SIZE.get() == TOTAL_PRODUCTION) {
                        System.out.println("本日发酵剂已生产完,共" + i + "份");
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }


        }
    }

    /**
     * 牛奶生产线程
     */
    static class MilkProducer implements Runnable {

        @Override
        public void run() {
            while (MILK_SIZE.get() < TOTAL_PRODUCTION * 2) {
                try {
                    MILK_QUEUE.put(1);
                    //System.out.println("生产1份牛奶");

                    //牛奶数量+1
                    int i = MILK_SIZE.incrementAndGet();
                    if (MILK_SIZE.get() == TOTAL_PRODUCTION * 2) {
                        System.out.println("本日牛奶已生产完,共" + i + "份");
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    /**
     * 货车发货线程
     */
    static class Trucking implements Runnable {
        @Override
        public void run() {

            while (true) {
                try {
                    //取奶酪装车准备发货
                    CHEESE_QUEUE.take();

                    int i1 = CHEESE_TAKE_TIMES.incrementAndGet();

                    if (i1 % 100 == 0) {
                        System.out.println("货车装满100份,发车");
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }

        }
    }

    public static void main(String[] args) {
        CHEESE_PRODUCER.execute(new CheeseProducer());

        STARTER_PRODUCER.execute(new StarterProducer());

        MILK_PRODUCER.execute(new MilkProducer());

        TRUCKING.execute(new Trucking());

        while (true) {
            if (CHEESE_SIZE.get() == TOTAL_PRODUCTION) {
                MILK_PRODUCER.shutdown();
                STARTER_PRODUCER.shutdown();
                CHEESE_PRODUCER.shutdown();
                TRUCKING.shutdown();
                System.exit(0);
            }

        }
    }

}

如上代码就是一个典型的生产者消费者代码,而且都是单线程生产和消费。

  • 1份奶酪需要2份牛奶和1份发酵剂,确定了2个生产者和一个消费者。
  • 货车从冷库里取奶酪,奶酪需要放在冷库里,确定了一个生产者和一个消费者
  • 题目要求的所有的生产和消费行为都是单线程的

我自己在实现的时候,从冷库取奶酪的时候,使用了5个线程从冷库里取奶酪,这样会导致在计算取多少次的时候,会导致数据打印出来会乱序。

题目要求的是每100份奶酪发一次车,所以需要在冷库里取100次,下面如果不加锁,会有问题,导致乱序

所以货车如果改成多线程,下面这几行代码需要加锁保证顺序

  CHEESE_QUEUE.take();

  int i1 = CHEESE_TAKE_TIMES.incrementAndGet();

  if (i1 % 100 == 0) {
        System.out.println("货车装满100份,发车");
  }

相关文章

  • 牛奶发酵剂奶酪,设计生产系统

    题目描述如下: 有一家生产奶酪的厂家,每天需要生产100000份奶酪卖给超市,通过一辆送货车发货,送货车辆每次送1...

  • 早餐

    蒸饺、炒蛋、奇异果、大枣、奶酪、牛奶

  • 油炸奶酪酥

    文/图 德鑫漫画 家中牛奶快过期了,趁着截止日期前解决掉,做做奶酪吧~~ 原来洋气高端的奶酪这么容易,牛奶...

  • 如何选择奶酪

    奶酪就是浓缩的牛奶,大概10公斤的牛奶才能制成1公斤的奶酪。宝宝喝牛奶最大的意义就是补充蛋白质和钙,然而由于宝宝的...

  • 谁动了我的奶酪

    如果说我们每天都在努力产出,就像我们每天都在生产奶酪,那么谁动了我们的奶酪了呢?我们生产了多少奶酪?谁又动了我们...

  • 慕斯—草莓优格

    优格:酸奶50克 奶酪20克 幼糖13克 牛奶12克 吉利丁4克 制作:奶油奶酪加糖搅拌光滑细腻 ,牛奶加热融化吉...

  • 狗狗的零食该升级了

    什么是奶酪(起司)? 奶酪(又名起司,是英文cheese的音译)是牛奶经浓缩,发酵而成的奶制品,它基本上排除了牛奶...

  • 超用户体验之高级定制系统

    超用户体验之高级定制系统 定制系统:销售、营销、设计、采购、生产、运输安装、交付 1、销售系统: (1)场景设计 ...

  • 白酒生产用曲有哪几类? 它们的特点又是什么?

    白酒生产所用曲包括大曲、小曲、麸曲和液体曲。 1.大曲 大曲是白酒生产的传统用曲,既是糖化剂,又是发酵剂,也是多种...

  • 柯林斯酸奶给你不一样的味道

    科林斯酸奶是以牛奶为原料,经过巴氏杀菌后再向牛奶中添加有益菌(发酵剂),经发酵后,再冷却灌装的一种酸奶制品。 目前...

网友评论

      本文标题:牛奶发酵剂奶酪,设计生产系统

      本文链接:https://www.haomeiwen.com/subject/hsybvktx.html