Object.wait()与Object.notify()的用法详细解析
wait、notify和notifyall方法是object类的final native方法。所以这些方法不能被子类重写,object类是所有类的超类,因此在程序中有以下三种形式调用wait等方法。
wait();//方式1:
this.wait();//方式2:
super.wait();//方式3
void notifyall()
解除所有那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个illegalmonitorstateexception异常。
void notify()
随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是锁的持有者,该方法抛出一个illegalmonitorstateexception异常。
void wait()
导致线程进入等待状态,直到它被其他线程通过notify()或者notifyall唤醒。该方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个illegalmonitorstateexception异常。
void wait(long millis)和void wait(long millis,int nanos)
导致线程进入等待状态直到它被通知或者经过指定的时间。这些方法只能在同步方法中调用。如果当前线程不是锁的持有者,该方法抛出一个illegalmonitorstateexception异常。
object.wait()和object.notify()和object.notifyall()必须写在synchronized方法内部或者synchronized块内部,这是因为:这几个方法要求当前正在运行object.wait()方法的线程拥有object的对象锁。即使你确实知道当前上下文线程确实拥有了对象锁,也不能将object.wait()这样的语句写在当前上下文中。如:
package edu.sjtu.erplab.objecttest;
class a
{
public synchronized void printthreadinfo() throws interruptedexception
{
thread t=thread.currentthread();
system.out.println("threadid:"+t.getid()+", threadname:"+t.getname());
}
}
public class objectwaittest {
public static void main(string args[])
{
a a=new a();
//因为printthreadinfo()方法抛出interruptedexception异常,所以这里必须使用try-catch块
try {
a.printthreadinfo();
a.wait();
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
}
}
程序运行会报错,运行结果如下:
threadid:1, threadname:main
exception in thread "main" java.lang.illegalmonitorstateexception
at java.lang.object.wait(native method)
at java.lang.object.wait(object.java:485)
at edu.sjtu.erplab.objecttest.objectwaittest.main(objectwaittest.java:24)
正确的写法应该是
package edu.sjtu.erplab.objecttest;
class a
{
public synchronized void printthreadinfo() throws interruptedexception
{
thread t=thread.currentthread();
system.out.println("threadid:"+t.getid()+", threadname:"+t.getname());
// this.wait();//一直等待
this.wait(1000);//等待1000ms
// super.wait(1000);
}
}
public class objectwaittest {
public static void main(string args[])
{
a a=new a();
//因为printthreadinfo()方法抛出interruptedexception异常,所以这里必须使用try-catch块
try {
a.printthreadinfo();
//a.wait();
} catch (interruptedexception e) {
// todo auto-generated catch block
e.printstacktrace();
}
thread t=thread.currentthread();
system.out.println("threadid:"+t.getid()+", threadname:"+t.getname());
}
}