java - 调用notifyAll时出现IllegalMonitorStateException

标签 java multithreading thread-safety reentrantlock illegalmonitorstateexcep

我有一段代码在调用notifyAll时给出IllegalMonitorException。当 enQueue() 时,线程添加数据并抛出非法MonitorException。

BlockingQueue.class:

public class BlockingQueue {
private Queue<Integer> 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());
        lock.wait();
    }
    System.out.println(" Adding "+d);
    queue.add(d);
    lock.notify();
    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());
        lock.wait();
    }
    int data = queue.remove();
    lock.notify();
    lock.unlock();
    return data;
}}

主类:

 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,"Consumer");
    Thread t2=new Thread(p, "producer");

    t1.start();
    t2.start();
}}

生产者.class:

 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();
        }
    }
}}

消费者.class:

public class Consumer implements Runnable {

private BlockingQueue queue;
Consumer(BlockingQueue q){
    this.queue=q;
}

public void consume(int data){
    System.out.println(" consume "+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("interrupted");
        }
    }
}}

输出:

添加94

线程“生产者”java.lang.IllegalMonitorStateException 中出现异常

at java.lang.Object.notify(Native Method)
at BlockingQueue.enQueue(BlockingQueue.java:23)
at Producer.run(Producer.java:20)
at java.lang.Thread.run(Thread.java:748)

最佳答案

以下代码修复了该问题

public class BlockingQueue {
    private Queue<Integer> 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();
        }
    }
}

说明: 您从不允许的非同步块(synchronized block)调用 waitnotify 。当您调用其中任何一个时,您应该对该对象进行监视器锁定。在本例中锁定

这里有一篇很好的文章,解释了为什么等待/通知必须始终位于同步块(synchronized block)中 https://stackoverflow.com/a/2779565/1891456

关于java - 调用notifyAll时出现IllegalMonitorStateException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59906952/

相关文章:

Java:连接数据库并返回查询结果

java - SQL正则表达式到Java正则表达式的转换器

java - JAVA方法中的线程互斥

java - Java中的线程安全交换

java - JSpinner 和双点或逗号作为分隔符

multithreading - Erlang 节点到节点消息传递吞吐量、超时和保证

Python 脚本在后台运行时挂起

c - 多线程代码中的结构内存布局

c - 静态内联函数线程安全吗?

java - 在 jpa 标准中, "in case there is at least 1 row return true"