“生产者-消费者-仓储”模型,包含三种角色:
1.生产者
2.消费者
3.仓库
离开了仓储,生产者消费者模型就显得没有说服力了。
对于此模型,应该明确一下几点:
1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
下面的三个类分别代表了生产者,消费者和仓库
package producerconsumer;
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Producer.java
* 2010-3-3
**/
public class Producer extends Thread{
Integer producedNumber;
Ware ware;
public Producer(Integer producedNumber, Ware ware){
this.producedNumber = producedNumber;
this.ware = ware;
}
public void run(){
try{
while(true){
ware.put(producedNumber);
}
}catch (Exception e) {
// TODO: handle exception
}
}
}
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Producer.java
* 2010-3-3
**/
public class Producer extends Thread{
Integer producedNumber;
Ware ware;
public Producer(Integer producedNumber, Ware ware){
this.producedNumber = producedNumber;
this.ware = ware;
}
public void run(){
try{
while(true){
ware.put(producedNumber);
}
}catch (Exception e) {
// TODO: handle exception
}
}
}
package producerconsumer;
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Consumer.java
* 2010-3-3
**/
public class Consumer extends Thread{
Integer consumedNumber;
Ware ware;
public Consumer(Integer consumedNumber, Ware ware){
this.consumedNumber = consumedNumber;
this.ware = ware;
}
public void run(){
try{
while(true){
ware.take(consumedNumber);
}
}catch (Exception e) {
// TODO: handle exception
}
}
}
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Consumer.java
* 2010-3-3
**/
public class Consumer extends Thread{
Integer consumedNumber;
Ware ware;
public Consumer(Integer consumedNumber, Ware ware){
this.consumedNumber = consumedNumber;
this.ware = ware;
}
public void run(){
try{
while(true){
ware.take(consumedNumber);
}
}catch (Exception e) {
// TODO: handle exception
}
}
}
package producerconsumer;
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Ware.java
* 2010-3-3
**/
public class Ware {
int capacity;
int size;
public Ware(int capacity){
this.capacity = capacity;
}
public void take(int number) throws InterruptedException{
synchronized (this) {
while(number>size){
System.out.println(Thread.currentThread().getName()+"========The consumer number "+number+" is greater than the size=="+size+".Wait to put.");
this.wait();
}
size = size -number;
System.out.println(Thread.currentThread().getName()+"========Consumer the product========"+number+";The ware has the product======"+size);
this.notifyAll();
}
}
public void put(int number) throws InterruptedException{
synchronized (this) {
while(size+number>capacity){
System.out.println(Thread.currentThread().getName()+"========The put number "+number+" plus the current ware size=="+size +" is greater than capacity=="+capacity+".Wait to consumer.");
this.wait();
}
size = size +number;
System.out.println(Thread.currentThread().getName()+"========Produced the product========"+number+";The ware has the product======"+size);
this.notifyAll();
}
}
public synchronized int size() {
return size;
}
/**
* <p>Description: Test</p>
* <p>Copyright (c) 2010</p>
* <p>Project:Test</p>
*
* @author Tomy Zhou
* @since 1.0
* @version producerconsumer; Ware.java
* 2010-3-3
**/
public class Ware {
int capacity;
int size;
public Ware(int capacity){
this.capacity = capacity;
}
public void take(int number) throws InterruptedException{
synchronized (this) {
while(number>size){
System.out.println(Thread.currentThread().getName()+"========The consumer number "+number+" is greater than the size=="+size+".Wait to put.");
this.wait();
}
size = size -number;
System.out.println(Thread.currentThread().getName()+"========Consumer the product========"+number+";The ware has the product======"+size);
this.notifyAll();
}
}
public void put(int number) throws InterruptedException{
synchronized (this) {
while(size+number>capacity){
System.out.println(Thread.currentThread().getName()+"========The put number "+number+" plus the current ware size=="+size +" is greater than capacity=="+capacity+".Wait to consumer.");
this.wait();
}
size = size +number;
System.out.println(Thread.currentThread().getName()+"========Produced the product========"+number+";The ware has the product======"+size);
this.notifyAll();
}
}
public synchronized int size() {
return size;
}
下面代码大家想想:
synchronized (this) {
while(size+number>capacity){
System.out.println(Thread.currentThread().getName()+"========The put number "+number+" plus the current ware size=="+size +" is greater than capacity=="+capacity+".Wait to consumer.");
this.wait();
}
while(size+number>capacity){
System.out.println(Thread.currentThread().getName()+"========The put number "+number+" plus the current ware size=="+size +" is greater than capacity=="+capacity+".Wait to consumer.");
this.wait();
}
为什么不能改成if (size+number>capacity)?
考虑下面的情况:
capacity:50
current size:40
生产线程Thread-0 put 20+ current size 40 = 60,线程阻塞,并释放锁
生产线程Thread-1 获取监控器的锁,并put10+currnet size 40=50,size=50,唤醒所有阻塞的线程
如果是if:Thread-0往下执行:size=50+20=70,显然超过了仓库的最大库存,在这种情况下就出现问题,如果改成while,Thread 0 仍然会阻塞,不会超过仓库的最大库存。