标签:分享 style col src 缺陷 生产 ack public 包含
首先,定义一个店员:店员包含进货、卖货方法;其次,定义一个生产者,生产者负责给店员生产产品;再者,定义一个消费者,消费者负责从店员那里消费产品。
店员:
/** * 店员 */ class Clerk { private int product = 0; /** * 进货 */ public synchronized void purchase() { if (product >= 10) { System.out.println("产品已满。。。"); } else { System.out.println(Thread.currentThread().getName() + ":" + ++product); } } /** * 卖货 */ public synchronized void sell() { if (product <= 0) { System.out.println("产品缺貨。。。"); } else { System.out.println(Thread.currentThread().getName() + ":" + --product); } } }
生产者
/** * 生产者 不断的生产产品给店员 * */ class Productor implements Runnable{ private Clerk clerk; public Productor(Clerk clerk){ this.clerk=clerk; } public void run() { for(int i=0;i<20;i++){ clerk.purchase(); } } }
消费者
/** * 消费者 不断的从店员那里消费产品 * */ class Consumer implements Runnable{ private Clerk clerk; public Consumer(Clerk clerk){ this.clerk=clerk; } public void run() { for(int i=0;i<20;i++){ clerk.sell(); } } }
此时,运行程序,运行结果如下:
Productor-A:1 Productor-A:2 Productor-A:3 Productor-A:4 Productor-A:5 Productor-A:6 Productor-A:7 Productor-A:8 Productor-A:9 Productor-A:10 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 产品已满。。。 Consumer-A:9 Consumer-A:8 Consumer-A:7 Consumer-A:6 Consumer-A:5 Consumer-A:4 Consumer-A:3 Consumer-A:2 Consumer-A:1 Consumer-A:0 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。 产品缺貨。。。
从运行打印结果可以发现这里存在两个问题:
1)一旦生产者发现店员产品已满时,仍然没有停止生产产品,在不断地生产生产产品;
2)一旦消费者发现店员产品缺货时,依然时不断地消费消费。
这里明显是有缺陷的,现实中应该是:一旦发现货物满时,就不在进货,而是开启卖货行为;当卖货行为发现无货时,开始进货行为。
消费者、生产者、客户端调用代码不变,只修改店员类:
/** * 店员 */ class Clerk { private int product = 0; /** * 进货 */ public synchronized void purchase() { if (product >= 10) { System.out.println("产品已满。。。"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(Thread.currentThread().getName() + ":" + ++product); this.notifyAll(); } } /** * 卖货 */ public synchronized void sell() { if (product <= 0) { System.out.println("产品缺貨。。。"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(Thread.currentThread().getName() + ":" + --product); this.notifyAll(); } } }
此时运行结果:
Productor-A:1 Consumer-A:0 产品缺貨。。。 Productor-A:1 Productor-A:2 Productor-A:3 Productor-A:4 Productor-A:5 Productor-A:6 Productor-A:7 Productor-A:8 Productor-A:9 Productor-A:10 产品已满。。。 Consumer-A:9 Consumer-A:8 Consumer-A:7 Consumer-A:6 Consumer-A:5 Consumer-A:4 Consumer-A:3 Consumer-A:2 Consumer-A:1 Consumer-A:0 产品缺貨。。。 Productor-A:1 Productor-A:2 Productor-A:3 Productor-A:4 Productor-A:5 Productor-A:6 Productor-A:7 Productor-A:8 Consumer-A:7 Consumer-A:6 Consumer-A:5 Consumer-A:4 Consumer-A:3 Consumer-A:2 Consumer-A:1
此时,从结果运行来说是按照我们希望的结果出现了。
改进后带来问题一:
修改店员类的最大进货数为1,把生产者一次生产20修改为2,消费者一次消费20也修改为2。
店员类:
/** * 店员 */ class Clerk { private int product = 0; /** * 进货 */ public synchronized void purchase() { if (product >= 1) { System.out.println("产品已满。。。"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(Thread.currentThread().getName() + ":" + ++product); this.notifyAll(); } } /** * 卖货 */ public synchronized void sell() { if (product <= 0) { System.out.println("产品缺貨。。。"); try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } else { System.out.println(Thread.currentThread().getName() + ":" + --product); this.notifyAll(); } } }
此时运行结果:
从运行结果上来看,程序是一个死锁现象。
为什么会发生死锁问题?
从运行结果上来看分析:
改进后带来问题二:
Java-JUC(八):使用wait,notify|notifyAll完成生产者消费者通信,虚假唤醒(Spurious Wakeups)问题出现场景,及问题解决方案。
标签:分享 style col src 缺陷 生产 ack public 包含
原文地址:https://www.cnblogs.com/yy3b2007com/p/8946696.html