A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

如下代码,是自己把书上的例子重写了一下,把需要同步的代码段放在了生产者和消费者的类里,没有放在容器(basket)类里,把同一个容器类的对象分别传给生产者和消费者对象,basketp和basketc指向的是同一个容器,但是程序运行的时候报出如下的运行时错误。查过错误信息,知道是同步的代码段出问题了,但是不知道该怎么改?

public class TestProducerConsumer{
        public static void main(String args[]){
                Basket basket = new Basket(6);
                Producer p1 = new Producer(basket);
                Consumer c1 = new Consumer(basket);

                new Thread(p1).start();  //启动生产者
                try {
                        Thread.sleep(3000);
                } catch(InterruptedException e){
                        e.printStackTrace();
                }
                new Thread(c1).start();  //启动消费者
        }       
}

class Mt{  //馒头类
        int mid;
        Mt(int mid){
                this.mid = mid;
        }
}

class Basket {  //篮子  先进后出
        public int index = 0;
        public int capacity;
        public Mt mtarr[];
        public Basket(int capacity) {
                this.capacity=capacity;
                mtarr = new Mt [this.capacity];
        }
}

class Producer implements Runnable {  //生产者
        private static int pid=0;
        public Basket basektp;

        Producer(Basket basket){
                basektp = basket;
        }
       
        public synchronized void run(){
                produce();
        }
       
        public synchronized void produce(){
                while(basektp.index == basektp.capacity)        {
                        try{
                                basektp.wait();
                        }catch (InterruptedException e)        {
                                e.printStackTrace();
                        }
                }
                basektp.mtarr[basektp.index] = new Mt(++pid);
                System.out.println("produced mid:"+basektp.mtarr[basektp.index].mid);
                basektp.index++;
                basektp.notifyAll();
        }
}

class Consumer implements Runnable {  //消费者

        public Basket basektc;
       
        Consumer(Basket basket){
                basektc = basket;
        }
       
        public synchronized void run(){
                consume();
        }

        public synchronized void consume(){
                while (basektc.index==0){
                        try{
                                basektc.wait();
                        }catch (InterruptedException e){
                                e.printStackTrace();
                        }
                }

                System.out.println("consumed mid:"+basektc.mtarr[basektc.index].mid);
                basektc.mtarr[basektc.index]=null;
                basektc.index--;
                basektc.notifyAll();
        }
}

输出的错误信息:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
        at java.lang.Object.notifyAll(Native Method)
        at Producer.produce(TestProducerConsumer.java:57)
        at Producer.run(TestProducerConsumer.java:43)
        at java.lang.Thread.run(Thread.java:662)
Exception in thread "Thread-1" java.lang.NullPointerException
        at Consumer.consume(TestProducerConsumer.java:82)
        at Consumer.run(TestProducerConsumer.java:70)
        at java.lang.Thread.run(Thread.java:662)

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

1 个回复

倒序浏览
1.java.lang.IllegalMonitorStateException异常原因:
   wait()/notify()/notifyAll(),应该是由监视器对象(锁对象)进行调用,而不能有其他对象调用
2.见代码中标注
  1. class Producer implements Runnable {  
  2.         private static int pid=0;
  3.         public Basket basektp;

  4.         Producer(Basket basket){
  5.                 basektp = basket;
  6.         }
  7.         
  8.         public synchronized void run(){
  9.                 produce();
  10.         }
  11.         
  12.         public synchronized void produce(){
  13.                 while(basektp.index == basektp.capacity) {
  14.                         try{
  15.                                 this.wait();                                        //1.修改basektp.wait();               
  16.                         }catch (InterruptedException e) {
  17.                                 e.printStackTrace();
  18.                         }
  19.                 }
  20.                 basektp.mtarr[basektp.index] = new Mt(++pid);
  21.                 System.out.println("produced mid:"+basektp.mtarr[basektp.index].mid);
  22.                 basektp.index++;
  23.                 this.notifyAll();                                         //1.修改basektp.notifyAll();  
  24.         }
  25. }

  26. class Consumer implements Runnable {  

  27.         public Basket basektc;
  28.         
  29.         Consumer(Basket basket){
  30.                 basektc = basket;
  31.         }
  32.         
  33.         public synchronized void run(){
  34.                 consume();
  35.         }

  36.         public synchronized void consume(){
  37.                 while (basektc.index==0){
  38.                         try{
  39.                                 this.wait();                                //1.修改basektc.wait();
  40.                         }catch (InterruptedException e){
  41.                                 e.printStackTrace();
  42.                         }
  43.                 }

  44.                 System.out.println("consumed mid:"+basektc.mtarr[basektc.index-1].mid);        //2.basektc.index需要-1,因为Producer生产了一个馒头,放在了数组mtarr[0],而basektc.index是1,你在这边准备消费mtarr[1],而mtarr[1]是null,所以造成NullPointerException异常
  45.                 basektc.mtarr[basektc.index]=null;
  46.                 basektc.index--;
  47.                 this.notifyAll();                                                        //1.修改basektc.notifyAll();
  48.         }
  49. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
贠(yun)靖 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马