java線程wait和notify詳解

    wait()和notify()是直接隸屬於Object類,也就是說,所有對象都擁有這一對方法。初看起來這十分 不可思議,但是實際上卻是很自然的,因爲這一對方法阻塞時要釋放佔用的鎖,而鎖是任何對象都具有的,調用任意對象的 wait() 方法導致線程阻塞,並且該對象上的鎖被釋放。而調用任意對象的notify()方法則導致因調用該對象的wait() 方法而阻塞的線程中隨機選擇的一個解除阻塞(但要等到獲得鎖後才真正可執行)。

 
    其次,wait()和notify()可在任何位置調用,但是這一對方法卻必須在 synchronized 方法或塊中調用,理由也很簡單,只有在 synchronized 方法或塊中當前線程才佔有鎖,纔有鎖可以釋放。同樣的道理,調用這一對方法的對象上的鎖必須爲當前線程所擁有,這樣纔有鎖可以 釋放。因此,方法調用必須放置在這樣的 synchronized 方法或塊中,該方法或塊的加鎖對象就是調用這些方法的對象。若不滿足這一條 件,則程序雖然仍能編譯,但在運行時會出現IllegalMonitorStateException 異常。
 
    wait() 和 notify() 方法的上述特性決定了它們經常和synchronized 方法或塊一起使用,將它們和操作系統的進程間通信機制作 一個比較就會發現它們的相似性:synchronized方法或塊提供了類似於操作系統原語的功能,它們的執行不會受到多線程機制的干擾,而這一對方法則 相當於 block 和wakeup 原語(這一對方法均聲明爲 synchronized)。它們的結合使得我們可以實現操作系統上一系列精妙的進程間 通信的算法(如信號量算法),並用於解決各種複雜的線程間通信問題。
 
關於 wait() 和 notify() 方法最後再說明兩點:
    第一:調用 notify() 方法導致解除阻塞的線程是從因調用該對象的 wait() 方法而阻塞的線程中隨機選取的,我們無法預料哪一個線程將會被選擇,所以編程時要特別小心,避免因這種不確定性而產生問題。
 
     第二:除了 notify(),還有一個方法 notifyAll() 也可起到類似作用,唯一的區別在於,調用 notifyAll() 方法將把因調 用該對象的 wait() 方法而阻塞的所有線程一次性全部解除阻塞。當然,只有獲得鎖的那一個線程才能進入可執行狀態。
 
相關wait和notify使用demo:
01 /**
02  * <pre>
03  * 子線程循環10次,接着主線程循環100次,接着有回到子線程循環10次,
04  * 接着再回到主線程循環100次,如此執行50次
05  * </pre>
06  * @author ketqi
07  */
08 public class WaitNotifyDemo {
09     public static void main(String[] args) {
10 
11         final Business business = new Business();
12         new Thread(new Runnable() {
13             @Override
14             public void run() {
15                 for (int i = 1; i <= 50; i++) {
16                     business.sub(i);
17                 }
18 
19             }
20         }).start();
21 
22         for (int i = 1; i <= 50; i++) {
23             business.main(i);
24         }
25     }
26 }
27 
28 class Business {
29     private boolean isMainThread = true;
30 
31     public synchronized void sub(int i) {
32         while (!isMainThread) {
33             try {
34                 this.wait();
35             } catch (InterruptedException e) {
36                 e.printStackTrace();
37             }
38         }
39         for (int j = 1; j <= 10; j++) {
40             System.out.println("sub thread sequence of " + j + ",loop of " + i);
41         }
42         isMainThread = false;
43         this.notify();
44     }
45 
46     public synchronized void main(int i) {
47         while (isMainThread) {
48             try {
49                 this.wait();
50             } catch (InterruptedException e) {
51                 e.printStackTrace();
52             }
53         }
54         for (int j = 1; j <= 100; j++) {
55             System.out.println("main thread sequence of " + j + ",loop of " + i);
56         }
57         isMainThread = true;
58         this.notify();
59     }
60 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章