Producer Consumer的Java实现抛出java.lang.IllegalMonitorStateException

时间:2016-04-26 06:21:34

标签: java multithreading exception-handling producer-consumer

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

}

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

我得到的完整例外情况如下。

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)

4 个答案:

答案 0 :(得分:6)

您正在拨打wait(),这相当于this.wait(),但您并未持有this的监视器。您在queue上持有显示器。所以它应该是queue.wait()。 (notify())相同。

答案 1 :(得分:3)

查看Javadoc for IllegalMonitorStateException

  

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

当你在没有拿着监视器的对象上尝试wait()(或notify())时,抛出异常;您已在队列上同步,但尝试wait() this wait(),这不是队列,而是runnable。 将queue.wait()更改为notify()queue.notify()更改为unlist应该有效。

答案 2 :(得分:2)

我认为我的代码正常运行......

如JB Nizet所述,您必须在queue对象上调用wait并通知。 我认为必须将此类对象声明为static才能由Producer和Consumer共享。

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

此外,在Producer和Consumer first 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");
     }

 }

enter image description here

答案 3 :(得分:0)

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