生产者消费者问题(使用notify和wait设计)

设计:产品-product类;

产品库:productRepository类

生产者线程

消费者线程

 

product.java

public class Product{
  private String name;
  private long productNo;
  public Product(String name,long productNo){
    this.name = name;
    this.productNo = productNo;
  }
  public String getName(){
    return name;
  }
  public void setName(){
    this.name = name;
  }
  public long getProductNo(){
    return productNo;
  }
  public void setProductNo(){
    this.productNo = productNo;
  }


  @重写
  public String toString(){
    return "Product{"+"name'="+name+'\"+",productNo["+productNo+'}';
  }
}

 

ProductRepository.java

public class ProductRepository(){
  private Vector<Product> products = new Vector<>();
  private static final int MAX_NUM = 10;

  public void produce(){
    synchronized(products){
      if(products.size()==MAX_NUM){
        try{
            wait();
        }catch(InterruptedException e){
          e.printStackTrace();
        }
      }
      //products.size()<MAX_NUM 如果仓库还没有满
      Product product = new Product("包子",System.currentTimeMillis());
      products.add(product);
      try{
        Thread.sleep(1000);
      }catch(InterruptedException e){
        e.printStackTrace();
      }
            System.out.println(Thread.currrentThread().getName()+"生产了: "+product+" ,产品仓库当前数量: "+ products.size());
      //通知等待的消费者来消费
      notify();
    }
  }


  public void consume(){
    synchronized(products){
      if(products.size()===0){
        try{
          wait();
        }catch(InterruptedException e){
          e.printStackTrace();
        }
      }
      Product product = products.firstElement();
      products.remove(0);
      System.out.println(Thread.currentThread().getName()+"消费了: "+ product+" ,产品仓库当前数量: "+ products.size());
      try{
        Thread.sleep(2000);
      }catch(InterruptedException){
        e.printStackTrace();
      }
      //通知生产者生产
      notify();
    }
  }
}

 

consumer.java

public class Consumer implements Runnable{
  private ProductRepository repository;

  public Consumer(ProductRepository repository){
    this.repository = repository;
  }

  @Override
  public void run(){
    while(true){
      repository.consume();
    }
  }
}

 

Producer.java

public class Producer implments Runnable{
  private ProductRepository repository;

  public Producer(ProductRepository repository){
    this.repository = repository;
  }

  @Override
  public void run(){
    while(true){
      repository.produce();
    }
  }
}

 

测试类

public class ProductorConsumerTest {


    /**
     * 一个生产者,一个消费者
     * @throws InterruptedException
     */
    public static void oneProducerAndOneConsumer() throws InterruptedException {
        ProductRepository repository = new ProductRepository();
        Consumer consumer = new Consumer(repository);
        Producer producer = new Producer(repository);
        Thread t1 = new Thread(producer,"producer-A");
        Thread t2 = new Thread(consumer,"consumer-B");
        t1.start();
        t2.start();
        t1.join();
        t2.join(); //join(): 主线程等待t1线程和禾t2线程都执行完
    }
    public static void main(String[] args) throws InterruptedException {
           oneProducerAndOneConsumer();
    }
}

结果:

Exception in thread "producer-A" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at com.gml.pinlor.thread.pcproblem.ProductRepository.produce(ProductRepository.java:33)
    at com.gml.pinlor.thread.pcproblem.Producer.run(Producer.java:17)
    at java.lang.Thread.run(Thread.java:745)
producer-A 生产了: Product{name='包子', productNo=1521786358450} ,产品仓库当前数量: 1
consumer-B 消费了: Product{name='包子', productNo=1521786358450} ,产品仓库当前数量: 0

java.lang.IllegalMonitorStateException是什么鬼?在API中是这么描述的:

Thrown to indicate that a thread has attempted to wait on an object’s monitor or to notify other threads waiting on an object’s monitor without owning the specified monitor(一个线程尝试等待一个对象的监视器,或者去通知其他正在等待对象监视器线程,却没有指明一个具体的监视器,才会抛出这个异常)

原来是将synchronized监视到products对象上了,但调用waitnotify方法却不是products对象,将ProductRepository.java换成:

public class ProductRepository {

    private Vector<Product> products = new Vector<>();
    private static final int MAX_NUM = 10;

    public void produce(){
        synchronized (products){
            if (products.size() == MAX_NUM){ //如果仓库已经满了
                try {
                    products.wait();      //让products等待!!!
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //products.size() < MAX_NUM 如果仓库还没有满
            Product product = new Product("包子", System.currentTimeMillis());
            products.add(product);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
            //通知等待的消费者来消费
            products.notify();
//            products.notifyAll();
        }
    }


    public void consume(){
        synchronized (products){
            if (products.size() == 0){ //产品仓库空了,等待生产者生产
                try {
                    products.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Product product = products.firstElement();
            products.remove(0);
            System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //通知生产者生产
            products.notify();
//            products.notifyAll();
        }
    }

}

结果:

producer-A 生产了: Product{name='包子', productNo=1521786975941} ,产品仓库当前数量: 1
consumer-B 消费了: Product{name='包子', productNo=1521786975941} ,产品仓库当前数量: 0
producer-A 生产了: Product{name='包子', productNo=1521786978944} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521786979944} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521786980944} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521786981945} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521786982945} ,产品仓库当前数量: 5
consumer-B 消费了: Product{name='包子', productNo=1521786978944} ,产品仓库当前数量: 4
consumer-B 消费了: Product{name='包子', productNo=1521786979944} ,产品仓库当前数量: 3

一个生产者,多个消费者

只需要在ProductRepository中将produce方法中products.notify()方法换成products.notifyAll()方法即可

public class ProductRepository {

    private Vector<Product> products = new Vector<>();
    private static final int MAX_NUM = 10;

    public void produce(){
        synchronized (products){
            if (products.size() == MAX_NUM){ //如果仓库已经满了
                try {
                    products.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //products.size() < MAX_NUM 如果仓库还没有满
            Product product = new Product("包子", System.currentTimeMillis());
            products.add(product);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
            //通知等待的消费者来消费
//            products.notify();
            products.notifyAll();
        }
    }


    public void consume(){
        synchronized (products){
            if (products.size() == 0){ //产品仓库空了,等待生产者生产
                try {
                    products.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Product product = products.firstElement();
            products.remove(0);
            System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //通知生产者生产
            products.notify();
//            products.notifyAll();
        }
    }
}

测试:

public class ProductorConsumerTest {

    /**
     * 一个生产者,多个消费者
     * @throws InterruptedException
     */
    public static void oneProducerAndMoreConsumer() throws InterruptedException {
        ProductRepository repository = new ProductRepository();
        Consumer consumer = new Consumer(repository);
        Consumer consumer2 = new Consumer(repository);
        Producer producer = new Producer(repository);
        Thread t1 = new Thread(producer,"producer-A");
        Thread t2 = new Thread(consumer,"consumer-B");
        Thread t3 = new Thread(consumer,"consumer-C");
        t1.start();
        t2.start();
        t3.start();
        t1.join();
        t2.join();
        t3.join();
    }
    public static void main(String[] args) throws InterruptedException {
 //        oneProducerAndOneConsumer();
         oneProducerAndMoreConsumer();
 //        moreProducerAndMoreConsumer();
     }
}
  •  
  • 结果:
producer-A 生产了: Product{name='包子', productNo=1521787226868} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521787227868} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521787228868} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521787229868} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521787230868} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787231868} ,产品仓库当前数量: 6
producer-A 生产了: Product{name='包子', productNo=1521787232868} ,产品仓库当前数量: 7
producer-A 生产了: Product{name='包子', productNo=1521787233868} ,产品仓库当前数量: 8
producer-A 生产了: Product{name='包子', productNo=1521787234868} ,产品仓库当前数量: 9
producer-A 生产了: Product{name='包子', productNo=1521787235868} ,产品仓库当前数量: 10
consumer-C 消费了: Product{name='包子', productNo=1521787226868} ,产品仓库当前数量: 9
consumer-C 消费了: Product{name='包子', productNo=1521787227868} ,产品仓库当前数量: 8
consumer-B 消费了: Product{name='包子', productNo=1521787228868} ,产品仓库当前数量: 7
consumer-C 消费了: Product{name='包子', productNo=1521787229868} ,产品仓库当前数量: 6
consumer-C 消费了: Product{name='包子', productNo=1521787230868} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787246869} ,产品仓库当前数量: 6

多个生产者,多个消费者

同样只需要修改ProductRepository中的consumer方法中的products.notity()products.notifyAll(),通知所有的生产者

public class ProductRepository {

    private Vector<Product> products = new Vector<>();
    private static final int MAX_NUM = 10;

    public void produce(){
        synchronized (products){
            if (products.size() == MAX_NUM){ //如果仓库已经满了
                try {
                    products.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            //products.size() < MAX_NUM 如果仓库还没有满
            Product product = new Product("包子", System.currentTimeMillis());
            products.add(product);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
            //通知等待的消费者来消费
//            products.notify();
            products.notifyAll();
        }
    }


    public void consume(){
        synchronized (products){
            if (products.size() == 0){ //产品仓库空了,等待生产者生产
                try {
                    products.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            Product product = products.firstElement();
            products.remove(0);
            System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //通知生产者生产
//            products.notify();
            products.notifyAll();
        }
    }

}

测试:

public class ProductorConsumerTest {

    /**
     * 多个生产者,多个消费者
     * @throws InterruptedException
     */
    public static void moreProducerAndMoreConsumer() throws InterruptedException {
        ProductRepository repository = new ProductRepository();
        Consumer consumer = new Consumer(repository);
        Consumer consumer1 = new Consumer(repository);
        Producer producer = new Producer(repository);
        Producer producer1 = new Producer(repository);
        Thread t1 = new Thread(producer,"producer-A");
        Thread t2 = new Thread(consumer,"consumer-B");
        Thread t3 = new Thread(consumer1,"consumer-C");
        Thread t4 = new Thread(producer1,"producer-D");
        t1.start();
        t4.start();
        t2.start();
        t3.start();

        t1.join();
        t4.join();
        t2.join();
        t3.join();
    }

    public static void main(String[] args) throws InterruptedException {
       // oneProducerAndOneConsumer();
        // oneProducerAndMoreConsumer();
       moreProducerAndMoreConsumer();
    }
}

结果:

producer-A 生产了: Product{name='包子', productNo=1521787607751} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521787608752} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521787609752} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521787610752} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521787611753} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787612753} ,产品仓库当前数量: 6
producer-A 生产了: Product{name='包子', productNo=1521787613753} ,产品仓库当前数量: 7
producer-A 生产了: Product{name='包子', productNo=1521787614753} ,产品仓库当前数量: 8
producer-D 生产了: Product{name='包子', productNo=1521787615753} ,产品仓库当前数量: 9
producer-D 生产了: Product{name='包子', productNo=1521787616753} ,产品仓库当前数量: 10
consumer-C 消费了: Product{name='包子', productNo=1521787607751} ,产品仓库当前数量: 9
consumer-B 消费了: Product{name='包子', productNo=1521787608752} ,产品仓库当前数量: 8
consumer-B 消费了: Product{name='包子', productNo=1521787609752} ,产品仓库当前数量: 7
consumer-B 消费了: Product{name='包子', productNo=1521787610752} ,产品仓库当前数量: 6
consumer-C 消费了: Product{name='包子', productNo=1521787611753} ,产品仓库当前数量: 5
consumer-C 消费了: Product{name='包子', productNo=1521787612753} ,产品仓库当前数量: 4
consumer-C 消费了: Product{name='包子', productNo=1521787613753} ,产品仓库当前数量: 3

 

posted @ 2019-03-23 09:43  strawqqhat  阅读(157)  评论(0编辑  收藏  举报
#home h1{ font-size:45px; } body{ background-image: url("放你的背景图链接"); background-position: initial; background-size: cover; background-repeat: no-repeat; background-attachment: fixed; background-origin: initial; background-clip: initial; height:100%; width:100%; } #home{ opacity:0.7; } .wall{ position: fixed; top: 0; left: 0; bottom: 0; right: 0; } div#midground{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -1; -webkit-animation: cc 200s linear infinite; -moz-animation: cc 200s linear infinite; -o-animation: cc 200s linear infinite; animation: cc 200s linear infinite; } div#foreground{ background: url("https://i.postimg.cc/z3jZZD1B/foreground.png"); z-index: -2; -webkit-animation: cc 253s linear infinite; -o-animation: cc 253s linear infinite; -moz-animation: cc 253s linear infinite; animation: cc 253s linear infinite; } div#top{ background: url("https://i.postimg.cc/PP5GtGtM/midground.png"); z-index: -4; -webkit-animation: da 200s linear infinite; -o-animation: da 200s linear infinite; animation: da 200s linear infinite; } @-webkit-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-o-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @-moz-keyframes cc { from{ background-position: 0 0; transform: translateY(10px); } to{ background-position: 600% 0; } } @keyframes cc { 0%{ background-position: 0 0; } 100%{ background-position: 600% 0; } } @keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-webkit-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-moz-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } } @-ms-keyframes da { 0%{ background-position: 0 0; } 100%{ background-position: 0 600%; } }