Search code examples
javamultithreadingexceptionproducer-consumer

Java implementation of Producer Consumer throws java.lang.IllegalMonitorStateException


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

}

I am getting a java.lang.IllegalMonitorStateException in the wait() part. I want to know what I am doing wrong here. Any ideas??

The complete exception that I get is as follows.

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)

Solution

  • I think that I got your code working ...

    As stated by JB Nizet you have to invoke wait and notify on the queue object. I think that such object must be declared static to be shared by Producer and Consumer.

    I have included while loops for the code to continue running until the end of time.

    Also, an extra notify is needed before Producer and Consumer first wait

    Here is your code with that changes included:

    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