IllegalMonitorStateException在调用notifyAll时发生

5 浏览
0 Comments

IllegalMonitorStateException在调用notifyAll时发生

我有一段代码,在调用notifyAll时出现了IllegalMonitorException异常。在enQueue()方法中,线程添加数据并抛出了IllegalMonitorException异常。\nBlockingQueue类:\n

public class BlockingQueue {
    private Queue queue = 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)

0
0 Comments

在这段代码中,出现了一个`IllegalMonitorStateException`的错误。这个错误的原因是在非同步块中调用了`wait`和`notify`方法,这是不允许的。当你调用这两个方法时,你应该在对象上获取监视器锁。在这种情况下,是`lock`对象。

这个问题可以通过在调用`wait`和`notify`方法之前,在同步块中获取`lock`对象的监视器锁来解决。

修复后的代码如下:

public class BlockingQueue {
    private Queue queue = 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`对象的监视器锁。这样,就可以正确地使用这两个方法了。

0