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