您当前的位置:首页 > 计算机 > 编程开发 > Java

java设计奶酪生产系统怎么实现_牛奶发酵剂奶酪,设计生产系统

时间:03-31来源:作者:点击数:

题目描述如下:

有一家生产奶酪的厂家,每天需要生产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 CHEESE_QUEUE = new LinkedBlockingQueue<>(1000);

/**

* 阻塞队列,用于存放生产的牛奶,生产者是牛奶,消费者是奶酪生产

*/

private static final BlockingQueue MILK_QUEUE = new LinkedBlockingQueue<>(2);

/**

* 阻塞队列,用于存放生产的发酵剂,生产者是发酵剂,消费者是奶酪生产

*/

private static final BlockingQueue 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份,发车");

}

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门