當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Java wait()和notify()的區別用法及代碼示例


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()。

相關用法


注:本文由純淨天空篩選整理自sanatr大神的英文原創作品 Difference Between wait() and notify() in Java。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。