【问题标题】:Java implementation of Producer Consumer throws java.lang.IllegalMonitorStateExceptionProducer Consumer 的 Java 实现抛出 java.lang.IllegalMonitorStateException
【发布时间】:2023-12-14 12:10:02
【问题描述】:
import java.util.LinkedList;
import java.util.Queue;

class Producer extends PubSub implements Runnable{

    @Override
    public void run() {
        synchronized(queue){
            if (queue.size() == 99){
                try { 
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            queue.add(2);
            try{
                Thread.sleep(1000);
            }
            catch (InterruptedException e){
                e.printStackTrace();
            }
            notify();
            }
        }       
}


class Consumer extends PubSub implements Runnable{

    @Override
    public void run() {
        synchronized(queue){
            if(queue.isEmpty()){
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }   
            }
            System.out.println(queue.poll());
        }

    }

}
public class PubSub {
    static Integer QUEUE_SIZE = 100;
    Queue<Integer> queue = new LinkedList<Integer>();
    public static void main(String[] args) {
        Producer producer = new Producer();
        Consumer consumer = new Consumer();
        Thread producerThread = new Thread(producer);
        Thread consumerThread = new Thread(consumer);
        producerThread.start();
        consumerThread.start();
        System.out.println("Started both the threads");
    }

}

我在wait() 部分得到一个java.lang.IllegalMonitorStateException。我想知道我在这里做错了什么。有什么想法吗??

我得到的完整异常如下。

Exception in thread "Thread-1" Started both the threads
java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at Consumer.run(PubSub.java:36)
    at java.lang.Thread.run(Thread.java:745)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at Producer.run(PubSub.java:23)
    at java.lang.Thread.run(Thread.java:745)

【问题讨论】:

  • 请提供完整的堆栈跟踪
  • 在问题中添加。

标签: java multithreading exception-handling producer-consumer


【解决方案1】:

你正在调用wait(),相当于this.wait(),但你没有拿着this的监视器。您将监视器放在queue 上。所以应该是queue.wait()。 (notify() 也一样)。

【讨论】:

  • 我正在做一些测试......成员“队列”不必是静态的才能由生产者和消费者共享?
【解决方案2】:

查看 IllegalMonitorStateException 的 Javadoc

https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalMonitorStateException.html

当您尝试wait()(或notify())在您不持有监视器的对象上时抛出异常;您已在队列上同步,但尝试在this 上进行wait(),这不是队列,而是可运行的。 将wait() 更改为queue.wait() 并将notify() 更改为queue.notify() 应该可以工作。

【讨论】:

    【解决方案3】:

    我认为我让你的代码工作了......

    正如 JB Nizet 所说,您必须在 queue 对象上调用等待和通知。 我认为这样的对象必须声明为static 才能由生产者和消费者共享。

    我已经包含了 while 循环,以便代码继续运行直到时间结束。

    另外,在生产者和消费者之前需要一个额外的notify wait

    这是包含更改的代码:

    import java.util.LinkedList;
    import java.util.Queue;
    
    class Producer extends PubSub implements Runnable{
    
        @Override
        public void run() {
             int index = 0;
    
             while (true) {
                synchronized(queue){
                    while (queue.size() == QUEUE_SIZE){
                        try {
                            System.out.println("Producer waits");
                            queue.notify();
                            queue.wait();
                        } catch (InterruptedException e) {
                           e.printStackTrace();
                        }
                    }
    
                    System.out.println("Produce element " + (++index));
                    queue.add(2);
                    queue.notify();
    
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e){
                        e.printStackTrace();
                    }
    
    
                }
            }
        }
    }
    
    
    class Consumer extends PubSub implements Runnable{
    
         @Override
         public void run() {
             while (true) {
                 synchronized(queue) {
    
                    while (queue.isEmpty()){
                        try {
                             System.out.println("Consumer waits");
                             queue.notify();
                             queue.wait();
                        } catch (InterruptedException e) {
                             e.printStackTrace();
                        }
                    }
    
                    System.out.println("Consume element " + queue.poll());
                    queue.notify();
    
                }
             }
    
         }
    
      }
    
    public class PubSub {
         static Integer QUEUE_SIZE = 100;
    
         static Queue<Integer> queue = new LinkedList<Integer>();
    
         public static void main(String[] args) {
              Producer producer = new Producer();
              Consumer consumer = new Consumer();
    
              Thread producerThread = new Thread(producer);
              Thread consumerThread = new Thread(consumer);
    
              producerThread.start();
              consumerThread.start();
    
              System.out.println("Started both the threads");
         }
    
     }
    

    【讨论】:

    • 消费者部分不工作。消费者线程最初启动并正在等待。生产者生产了所有元素,但消费者不接受。
    • 您确定已复制所有更改吗?我刚刚再次运行它,它的工作原理
    【解决方案4】:

    线程只能在它已经获得锁的对象上调用 notify() 或 wait()。在您的程序中,线程已锁定队列对象,然后您的线程正在对此调用等待。

    【讨论】:

      最近更新 更多