-1

I have created an java thread and passed an stack reference to it's constructor, which initialize thread stack reference. In run method i have created an synchronized block with that stack object, the moment am calling wait in run inside synchronized block , i am getting IllegalMonitorStateException.

Thread Class :

public class Producer extends Thread {

Stack<String> stack=null;

public Producer(Stack<String> stack) {
    this.stack=stack;
}

@Override
public void run() {

    synchronized (stack) {
        if(stack.isEmpty()){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }       
}
}

Main Class:

public class MainClass {

public static void main(String[] args) {

    Stack<String> stack=new Stack<String>();

    Producer p=new Producer(stack);
    p.start();
}
}

Output :

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at demo.Producer.run(Producer.java:20)
Ammi
  • 21
  • 6

1 Answers1

1

For wait() (or notify()) to work, you must call it on the same object. What you have now is the same as

 synchronized (stack) {
    if(stack.isEmpty()){
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 }  

instead you should do

 synchronized (stack) {
    if(stack.isEmpty()){
        try {
            stack.wait(); // wait on the same object synchronized.
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 }  

Note: as wait can wake spuriously you have do this in a loop or your method could return prematurely.

 synchronized (stack) {
    while (stack.isEmpty()){
        try {
            stack.wait(); 
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
 }  
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130