• 生产者消费者问题(使用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
  • 相关阅读:
    计算机二级-C语言-程序修改题-190114记录-对整型变量进行取余操作可以取得各个位上的值。
    计算机二级C语言选择题错题知识点记录。
    计算机二级-C语言-对文件的读写操作。链表的定义与赋值。对字符串的遍历和处理。
    二十七、Java基础之数组的排列
    二十六、Java语言之二维数组
    二十五、Java基础之一维数组
    二十四、Java基础之自定义异常
    二十三、Java基础之异常及异常处理机制
    二十二、Java基础之内部类
    二十一、Java基础之访问控制权限
  • 原文地址:https://www.cnblogs.com/strawqqhat/p/10602178.html
Copyright © 2020-2023  润新知