java中的wait(),notify(),notifyAll(),synchronized方法


wait(),notify(),notifyAll()三個方法不是Thread的方法,而是Object的方法。意味着所有對象都有這三個方法,因為每個對象都有鎖,所以自然也都有操作鎖的方法了。這三個方法最終調用的都是jvm級的native方法。隨着jvm運行平台的不同可能有些許差異。

 

java文檔的解釋

wait導致當前的線程等待,直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法。當前的線程必須擁有此對象監視器。該線程發布對此監視器的所有權並等待,直到其他線程通過調用 notify 方法,或 notifyAll 方法通知在此對象的監視器上等待的線程醒來。然后該線程將等到重新獲得對監視器的所有權后才能繼續執行.

  notify喚醒在此對象監視器上等待的單個線程。如果所有線程都在此對象上等待,則會選擇喚醒其中一個線程。直到當前的線程放棄此對象上的鎖定,才能繼續執行被喚醒的線程。此方法只應由作為此對象監視器的所有者的線程來調用.

  "當前的線程必須擁有此對象監視器"與"此方法只應由作為此對象監視器的所有者的線程來調用"說明wait方法與notify方法必須在同步塊內執行,即synchronized(obj之內).

  調用對像wait方法后,當前線程釋放對像鎖,進入等待狀態.直到其他線程(也只能是其他線程)通過notify 方法,或 notifyAll.該線程重新獲得對像鎖.

 

例子代碼:

說明:線程運行3秒后調用wait等待,6秒后主線程調用notify喚醒等待線程。

 1 /**
 2  * Created on 2016/1/31.
 3  */
 4 public class MyThread implements Runnable {
 5     private Object flag;
 6     private String threadName;
 7 
 8     public MyThread(Object flag,String threadName) {
 9         this.flag = flag;
10         this.threadName = threadName;
11     }
12 
13     @Override
14     public void run(){
15         try{
16             for(int i = 0; i < 10;i++){
17                 if(i == 3){
18                     synchronized (this.flag){
19                         System.out.println("3秒后線程調用wait睡眠");
20                         this.flag.wait();
21                     }
22                 }
23                 System.out.println(this.threadName + " " + i);
24                 Thread.sleep(1000);
25             }
26         } catch(InterruptedException e){
27             e.printStackTrace();
28         }
29 
30     }
31 }

 

main方法:

 1 import java.io.IOException;
 2 
 3 /**
 4  * Created  on 2016/1/31.
 5  */
 6 public class TestMain {
 7     public static void main(String[] args) {
 8         Object object = new Object();
 9         MyThread myThread1 = new MyThread(object,"thread1");
10 //        MyThread myThread2 = new MyThread(object,"thread2");
11         Thread test1 = new Thread(myThread1);
12         test1.start();
13 
14 //        Thread test2 = new Thread(myThread1);
15 //        test2.start();
16 
17         try{
18             Thread.sleep(6000);
19             System.out.println("6秒后喚醒線程");
20             synchronized (object){
21                 object.notify();
22             }
23             System.in.read();
24         } catch(InterruptedException e){
25             e.printStackTrace();
26         } catch(IOException e){
27             e.printStackTrace();
28         }
29 
30     }
31 }

結果:

 

 

測試notifyAll(MyThread代碼不變)

main方法代碼:

 1 import java.io.IOException;
 2 
 3 /**
 4  * Created on 2016/1/31.
 5  */
 6 public class TestMain {
 7     public static void main(String[] args) {
 8         Object object = new Object();
 9         MyThread myThread1 = new MyThread(object,"thread1");
10         MyThread myThread2 = new MyThread(object,"thread2");
11         Thread test1 = new Thread(myThread1);
12         test1.start();
13 
14         Thread test2 = new Thread(myThread2);
15         test2.start();
16 
17         try{
18             Thread.sleep(6000);
19             System.out.println("6秒后喚醒線程");
20             synchronized (object){
21                 object.notifyAll();
22             }
23             System.in.read();
24         } catch(InterruptedException e){
25             e.printStackTrace();
26         } catch(IOException e){
27             e.printStackTrace();
28         }
29 
30     }
31 }

結果截圖:

 

 


免責聲明!

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



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