Java Threading wait()和Notify()似乎特别有用

时间:2012-08-28 08:17:31

标签: java multithreading

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

这是演示wait()和notify()的简单代码, 在myThreadRun类中,run()方法只执行wait()并且foo()方法执行notify() 如上面的代码中所示,如果我执行mThRun.notify()程序崩溃,但mThRun.foo()运行顺利,并提供了急需的结果。我需要知道为什么?

3 个答案:

答案 0 :(得分:3)

您需要拥有对象的监视器obj.wait()obj.notify()

这就是为什么它在synchronized mThRun块内调用但不在外面调用的原因。因此,如果您将mThRun.notify();放在同步块中,它就会起作用,如下所示:

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

答案 1 :(得分:1)

在您的情况下,您获得IllegalMonitorStateException

  

抛出此异常表示某个线程试图在对象的监视器上等待,或者在没有指定监视器的情况下通知在对象监视器上等待的其他线程。

换句话说,您没有持有您尝试通知的对象的锁定。拥有不同对象的锁定无济于事。


当您使用notify()和wait()时,您需要更改状态并检查它。如果你不这样做,你可以找到

  • 在wait()之前调用notify()并且信号丢失
  • wait()过早醒来

您不能认为通知/等待是一种可靠的消息传递协议。

我建议您考虑使用并发库,这在大多数情况下是Java 5.0(2004)的更好选择

答案 2 :(得分:0)

可能你正在努力等待/通知。它非常简单。您需要知道的是哪个对象用于监视器锁定。为了使相同的代码工作,我修改了相同的代码:(我把MAK注释放在我改变代码的地方,希望它有用)

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

    }
}