IllegalMonitorStateException在调用notifyAll时发生
IllegalMonitorStateException在调用notifyAll时发生
我有一段代码,在调用notifyAll时出现了IllegalMonitorException异常。在enQueue()方法中,线程添加数据并抛出了IllegalMonitorException异常。\nBlockingQueue类:\n
public class BlockingQueue { private Queuequeue = new LinkedList<>(); private int maxCount; private Lock lock = new ReentrantLock(); BlockingQueue(int maxCount){ this.maxCount=maxCount; } public void enQueue(int d) throws InterruptedException { lock.lock(); if(queue.size() >= maxCount){ System.out.println("正在等待入队 " + Thread.currentThread().getName() + " 大小 " + queue.size()); lock.wait(); } System.out.println(" 添加 " + d); queue.add(d); lock.notify(); lock.unlock(); } public Integer deQueue() throws InterruptedException { lock.lock(); if(queue.size()==0){ System.out.println("正在等待出队 " + Thread.currentThread().getName() + " 大小 " + queue.size()); lock.wait(); } int data = queue.remove(); lock.notify(); lock.unlock(); return data; } }
\nMain类:\n
public class Main { public static void main(String args[]){ BlockingQueue queue=new BlockingQueue(10); Producer p = new Producer(queue); Consumer c = new Consumer(queue); Thread t1=new Thread(c,"消费者"); Thread t2=new Thread(p, "生产者"); t1.start(); t2.start(); } }
\nProducer类:\n
public class Producer implements Runnable { private BlockingQueue q; Producer(BlockingQueue qu){ this.q=qu; } public Integer generateWork() throws InterruptedException { return new Random().nextInt(100); } @Override public void run() { for(int i =0; i<100; i++){ try { Thread.sleep(100); q.enQueue(generateWork()); } catch (InterruptedException e) { e.printStackTrace(); } } } }
\nConsumer类:\n
public class Consumer implements Runnable { private BlockingQueue queue; Consumer(BlockingQueue q){ this.queue=q; } public void consume(int data){ System.out.println(" 消费 " + data); } @Override public void run() { for(int i=0; i < 100; i++){ try { Thread.sleep(1000); consume(queue.deQueue()); } catch (InterruptedException e) { System.out.println("中断"); } } } }
\n输出:\nAdding 94\nException in thread \"producer\" java.lang.IllegalMonitorStateException\nat java.lang.Object.notify(Native Method)\nat BlockingQueue.enQueue(BlockingQueue.java:23)\nat Producer.run(Producer.java:20)\nat java.lang.Thread.run(Thread.java:748)
在这段代码中,出现了一个`IllegalMonitorStateException`的错误。这个错误的原因是在非同步块中调用了`wait`和`notify`方法,这是不允许的。当你调用这两个方法时,你应该在对象上获取监视器锁。在这种情况下,是`lock`对象。
这个问题可以通过在调用`wait`和`notify`方法之前,在同步块中获取`lock`对象的监视器锁来解决。
修复后的代码如下:
public class BlockingQueue { private Queuequeue = new LinkedList<>(); private int maxCount; private Lock lock = new ReentrantLock(); BlockingQueue(int maxCount) { this.maxCount = maxCount; } public void enQueue(int d) throws InterruptedException { lock.lock(); if (queue.size() >= maxCount) { System.out.println("going to wait enqueu " + Thread.currentThread().getName() + " size " + queue.size()); waitInternal(); } System.out.println(" Adding " + d); queue.add(d); notifyInternal(); lock.unlock(); } public Integer deQueue() throws InterruptedException { lock.lock(); if (queue.size() == 0) { System.out.println("going to wait dequeue " + Thread.currentThread().getName() + " size " + queue.size()); waitInternal(); } int data = queue.remove(); notifyInternal(); lock.unlock(); return data; } private void waitInternal() throws InterruptedException { synchronized (lock) { lock.wait(); } } private void notifyInternal() throws InterruptedException { synchronized (lock) { lock.notify(); } } }
这段代码修复了`IllegalMonitorStateException`问题,确保了在调用`wait`和`notify`方法之前获取了`lock`对象的监视器锁。这样,就可以正确地使用这两个方法了。