6
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)
station
  • 6,715
  • 14
  • 55
  • 89

4 Answers4

6

You're calling wait(), which is equivalent to this.wait(), but you're not holding the monitor of this. You're holding the monitor on queue. So it should be queue.wait(). (same for notify()).

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I've being doing some testing ... Member 'queue' don't have to be static to be shared by Producer and Consumer? – RubioRic Apr 26 '16 at 06:49
3

Check out the Javadoc for IllegalMonitorStateException

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

The exception is thrown when you attempt to wait() (or notify()) on an object of which you don't hold the monitor; You have synchronized on queue, but attempted to wait() on this, which is not the queue, rather the runnable. Changing wait() to queue.wait() and notify() to queue.notify() should work.

Aamir Khan
  • 2,945
  • 2
  • 25
  • 32
2

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

RubioRic
  • 2,442
  • 4
  • 28
  • 35
  • The consumer part is not working. The consumer thread starts initially and is waiting. The producer produced all the elements but then consumer does not pick up. – station Apr 26 '16 at 07:18
  • Are you sure that you have copied all the changes? I've just run it again and it works – RubioRic Apr 26 '16 at 07:20
0

A thread can call notify() or wait() only on an object on which it has already acquired lock. In your program thread has lock on queue object and then your thread is calling wait on this.

sachin thakur
  • 91
  • 2
  • 9