wait()和notify()的理解與使用


void notify() 
Wakes up a single thread that is waiting on this object’s monitor. 
譯:喚醒在此對象監視器上等待的單個線程

void notifyAll() 
Wakes up all threads that are waiting on this object’s monitor. 
譯:喚醒在此對象監視器上等待的所有線程

void wait( ) 
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll( ) method for this object. 
譯:導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法

void wait(long timeout) 
Causes the current thread to wait until either another thread invokes the notify( ) method or the notifyAll( ) method for this object, or a specified amount of time has elapsed. 
譯:導致當前的線程等待,直到其他線程調用此對象的notify() 方法或 notifyAll() 方法,或者指定的時間過完。

void wait(long timeout, int nanos) 
Causes the current thread to wait until another thread invokes the notify( ) method or the notifyAll( ) method for this object, or some other thread interrupts the current thread, or a certain amount of real time has elapsed. 
譯:導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法,或者其他線程打斷了當前線程,或者指定的時間過完。

上面是官方文檔的簡介,下面我們根據官方文檔總結一下:

  • wait( ),notify( ),notifyAll( )都不屬於Thread類,而是屬於Object基礎類,也就是每個對象都有wait( ),notify( ),notifyAll( ) 的功能,因為每個對象都有鎖,鎖是每個對象的基礎,當然操作鎖的方法也是最基礎了。

  • 當需要調用以上的方法的時候,一定要對競爭資源進行加鎖,如果不加鎖的話,則會報 IllegalMonitorStateException 異常

  • 當想要調用wait( )進行線程等待時,必須要取得這個鎖對象的控制權(對象監視器),一般是放到synchronized(obj)代碼中。

  • while循環里而不是if語句下使用wait,這樣,會在線程暫停恢復后都檢查wait的條件,並在條件實際上並未改變的情況下處理喚醒通知

  • 調用obj.wait( )釋放了obj的鎖,否則其他線程也無法獲得obj的鎖,也就無法在synchronized(obj){ obj.notify() } 代碼段內喚醒A。

  • notify( )方法只會通知等待隊列中的第一個相關線程(不會通知優先級比較高的線程)

  • notifyAll( )通知所有等待該競爭資源的線程(也不會按照線程的優先級來執行)

  • 假設有三個線程執行了obj.wait( ),那么obj.notifyAll( )則能全部喚醒tread1,thread2,thread3,但是要繼續執行obj.wait()的下一條語句,必須獲得obj鎖,因此,tread1,thread2,thread3只有一個有機會獲得鎖繼續執行,例如tread1,其余的需要等待thread1釋放obj鎖之后才能繼續執行。

  • 當調用obj.notify/notifyAll后,調用線程依舊持有obj鎖,因此,thread1,thread2,thread3雖被喚醒,但是仍無法獲得obj鎖。直到調用線程退出synchronized塊,釋放obj鎖后,thread1,thread2,thread3中的一個才有機會獲得鎖繼續執行。

測試用例:

 1 package test;
 2 
 3 /**
 4  * @author zsh
 5  * @company wlgzs
 6  * @create 2019-02-25 9:02
 7  * @Describe 多線程方法wait() and notify() 方法測試
 8  */
 9 public class WaitNotifyTest {
10 
11     // 在多線程間共享的對象上使用wait
12     private String[] shareObj = {"true"};
13 
14     //線程等待
15     class ThreadWait extends Thread{
16 
17         public ThreadWait(String name){
18             super(name);
19         }
20 
21         @Override
22         public void run() {
23             synchronized (shareObj){
24                 while ("true".equals(shareObj[0])){
25                     System.out.println("線程"+this.getName()+"開始等待");
26                     long startTime = System.currentTimeMillis();
27                     try {
28                         shareObj.wait();
29                     } catch (InterruptedException e) {
30                         e.printStackTrace();
31                     }
32                     long endTime = System.currentTimeMillis();
33                     System.out.println("線程"+this.getName()+"等待的時間為"+
34                             (endTime - startTime));
35                 }
36             }
37             System.out.println("線程" + this.getName() + "等待結束");
38         }
39     }
40 
41     //線程喚醒
42     class ThreadNotify extends Thread{
43 
44         public ThreadNotify(String name){
45             super(name);
46         }
47 
48         @Override
49         public void run() {
50             try {
51                 // 給等待線程等待時間
52                 sleep(3000);
53             } catch (InterruptedException e) {
54                 e.printStackTrace();
55             }
56             synchronized (shareObj){
57                 System.out.println("線程" + this.getName() + "開始准備通知");
58                 shareObj[0] = "false";
59                 shareObj.notifyAll();
60                 System.out.println("線程" + this.getName() + "通知結束");
61             }
62             System.out.println("線程" + this.getName() + "運行結束");
63         }
64     }
65 
66     public static void main(String[] args) {
67         WaitNotifyTest waitNotifyTest = new WaitNotifyTest();
68         ThreadWait threadWait1 = waitNotifyTest.new ThreadWait("wait thread1");
69         /**
70          * 優先級   : 只能反映線程的 重要程度 或者是 緊急程度 , 不能決定 是否一定先執行
71          * setPriority()
72          * 1~10   1最低  10最高    5是默認值
73          */
74         threadWait1.setPriority(2);
75         ThreadWait threadWait2 = waitNotifyTest.new ThreadWait("wait thread2");
76         threadWait2.setPriority(3);
77         ThreadWait threadWait3 = waitNotifyTest.new ThreadWait("wait thread3");
78         threadWait3.setPriority(4);
79 
80         ThreadNotify threadNotify = waitNotifyTest.new ThreadNotify("notify thread");
81 
82         threadNotify.start();
83         threadWait1.start();
84         threadWait2.start();
85         threadWait3.start();
86     }
87 
88 
89 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM