wait()和notify()是Object類的方法。將它們引入輪詢的部分方式,這是反複檢查要滿足的條件的過程。輪詢會大量浪費CPU資源,因此不是首選。
wait()具有3種變化:
1.不帶任何參數的基本版本
public final void wait() // will cause thread to wait till notify is called
2.版本采用單個超時參數
public final void wait(long timeout) // will cause thread to wait either till notify is called or // till timeout (One which occurs earlier)
3.帶有超時參數和納秒參數的版本,以提高精度
public final void wait(long timeout, int nanoseconds)
notify()有1個簽名
public final void notify() // Function does not take any argument
Wait() | notify() |
---|---|
在持有監視器鎖的線程上調用wait()時,它將放棄監視器鎖並進入等待狀態。 | 在持有監視器鎖的線程上調用notify()時,它表示該線程即將釋放該鎖。 |
一次可能有多個線程處於等待狀態。 |
等待線程之一是隨機選擇的,並被通知。然後,被通知的線程退出等待狀態並進入阻塞狀態,在該狀態下等待,直到前一個線程放棄了該鎖並且該線程已獲取了該鎖。一旦獲得了鎖,它將進入可運行狀態,在該狀態下等待CPU時間,然後開始運行。 |
下麵是wait()和notify()方法的演示:
Java
// Java Program to demonstrate usage of wait() and notify()
class demo {
// variable to check if part1 has returned
// volatile used to prevent threads from
// storing local copies of variable
volatile boolean part1done = false;
// method synchronized on this
// i.e. current object of demo
synchronized void part1()
{
System.out.println("Welcome to India");
part1done = true;
System.out.println(
"Thread t1 about to surrender lock");
// notify the waiting thread, if any
notify();
}
// method synchronized on this
// i.e. current object of demo
synchronized void part2()
{
// loop to prevent spurious wake-up
while (!part1done) {
try {
System.out.println("Thread t2 waiting");
// wait till notify is called
wait();
System.out.println(
"Thread t2 running again");
}
catch (Exception e) {
System.out.println(e.getClass());
}
}
System.out.println("Do visit Taj Mahal");
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo calss
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
}
}
輸出
Thread t2 waiting Welcome to India Thread t1 about to surrender lock Thread t2 running again Do visit Taj Mahal
各種例外
A.wait()
- 必須將wait()封裝在try-catch塊中,因為如果處於等待狀態的線程被中斷,那麽它將拋出InterruptedException。
- 如果超時值是負數或納秒值不在0到9,99,999之間,則等待住房參數的其他兩個變體將引發IllegalArgumentException。
下麵是異常處理的實現。
Java
// Program demonstrating occurance of InterruptedException
class demo {
volatile boolean part1done = false;
synchronized void part1()
{
System.out.println("Welcome to India");
part1done = true;
// notify() has been commented, waiting
// thread remains waiting forever notify();
}
synchronized void part2()
{
while (!part1done) {
try {
wait();
}
catch (Exception e) {
System.out.println("Exception:"
+ e.getClass());
// quit program after exception is thrown
System.exit(-1);
}
}
System.out.println("Do visit Taj Mahal");
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo class
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
// This is a counter which will
// interrupt Thread t2 after 3 seconds
long startTime = System.currentTimeMillis();
while (true) {
if (System.currentTimeMillis() - startTime
> 3000)
t2.interrupt();
}
}
}
輸出
Welcome to India Exception:class java.lang.InterruptedException
B.notify()
與wait()不同,notify方法不會引發InterruptedException,因此不是強製性的將其容納在try-catch塊中
注意:
- wait()和notify()都有拋出IllegalMonitorStateException的趨勢
- 當線程持有對象A的監視器鎖並嘗試在對象B上調用wait或notify時,會發生這種情況。
- 在前麵的所有示例中,方法都是在“this”上同步的,即用於調用這些方法的對象(obj)。同樣,將wait()和notify()分別稱為this.wait()和this.notify()(此用法是多餘的)。因此,沒有問題。
- 在下麵的示例中,方法part1和part2現在在Integer對象上同步,但是仍在調用這些方法(obj)的對象上調用wait()和notify()。
- 這將導致IllegalMonitorStateException
下麵是異常處理的實現。
Java
// Program to demonstrate IllegalMonitorStateException
class demo {
volatile boolean part1done = false;
// Made an Integer object a
// and set it randomly to 5
Integer a = 5;
void part1()
{
// Synchronized code on a
synchronized (a)
{
System.out.println("Welcome to India");
part1done = true;
// calling this.notify()
notify();
}
}
void part2()
{
// Synchronized code on a
synchronized (a)
{
while (!part1done) {
try {
// calling this.wait()
wait();
}
catch (Exception e) {
System.out.println("Exception:"+e.getClass());
System.exit(-1);
}
}
System.out.println("Do visit Taj Mahal");
}
}
}
public class Main {
public static void main(String[] args)
{
// Make an instance of demo class
demo obj = new demo();
// Thread t1 will call part1()
Thread t1 = new Thread(new Runnable() {
public void run() { obj.part1(); }
});
// Thread t2 will call part2()
Thread t2 = new Thread(new Runnable() {
public void run() { obj.part2(); }
});
// Start t2 and then t1
t2.start();
t1.start();
}
}
輸出
Exception:class java.lang.IllegalMonitorStateException
要修複以上代碼,隻需在第19行將notify()替換為a.notify(),並在第31行將wait()替換為a.wait()。
相關用法
- Java notify()和notifyAll()的區別用法及代碼示例
- Java wait和sleep的區別用法及代碼示例
- Java wait()和notifyall()的區別用法及代碼示例
- Java super()和this()的區別用法及代碼示例
- Java throw和throws的區別用法及代碼示例
注:本文由純淨天空篩選整理自sanatr大神的英文原創作品 Difference Between wait() and notify() in Java。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。