简体   繁体   中英

A Java Threading wait() and Notify() seems to work peculiarly

class myThreadRun implements Runnable
{

    public void run() {
        roo();
    }
    public synchronized void roo()
    {
        System.out.println("In thread before wait " + Thread.currentThread().getName());
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(null, "After wait in\n"+Thread.currentThread().getName());
        System.out.println("In thread after wait " + Thread.currentThread().getName());
        //notify();
    }

    public synchronized void foo()
    {
        notify();
    }
}

public class ThreadingDemo {

    public synchronized void Start()
    {
        System.out.println("Labamba");
        myThreadRun mThRun =  new myThreadRun();
        Thread thread =  new Thread(mThRun);
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        //mThRun.foo(); //This works
        //mThRun.notify(); //crash
        //thread.notify();//crash
        try {
            thread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
public static  void main(String[] args) {
        new ThreadingDemo().Start();
    }

This is simple code to demonstrate wait() and notify(), In the myThreadRun class run() method just does wait() and foo() method does notify() as indicated in the code above, if I do mThRun.notify() the program crashes, but mThRun.foo() runs the without a hitch and gives the much needed result. I need to know why?

You need to own the monitor for the object to all obj.wait() and obj.notify() .

That is why it works when called within the synchronized block on mThRun but not outside. So if you put the mThRun.notify(); in a synchronized block, it works, like this:

synchronized (mThRun) {
    mThRun.notify();
}

In your case you are getting an IllegalMonitorStateException .

Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

Put another way, you don't hold the lock of the object you are trying to notify. Having the lock of a different object doesn't help.


When you use notify() and wait() you need to change a state and check for it. If you don't do this, you can find that either

  • notify() is called before wait() and the signal is lost
  • wait() wakes prematurely

You cannot assume notify/wait is a reliable messaging protocol.

I suggest you consider using the concurrency library which is a better choice in most cases from Java 5.0 (2004)

May be you are going very hard with wait/notify. Its very simple. what you need to know is which object is used for monitor lock. To make the same code working i have modified the same code: ( I have put MAK comment where i changed the code, hope its helpful)

class MyThreadRun implements Runnable {
    public void run() {
        roo();
    }
    public synchronized void roo() {
        System.out.println("In thread before wait " + this);
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(null, "After wait in\n" + Thread.currentThread().getName());
        System.out.println("In thread after wait " + Thread.currentThread().getName());
    }

}

public class ThreadingDemo {

    public static void main(String[] args) {
        MyThreadRun mThRun = new MyThreadRun();
        System.out.println("Labamba: " +mThRun);
        Thread thread = new Thread(mThRun);
        thread.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        //mThRun.foo(); //This works  //MAK: no sense
        //mThRun.notify(); //crash   //MAK: Need monitor lock
        synchronized (mThRun) {
            mThRun.notify();//crash                  //MAK: will work now
        }
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM