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