Java中wait,notify方法

一.介紹

wait(),notify(),notifyAll()方法是位於Object類的方法,這三個方法調用的都是jvm的 native方法。

  • wait()方法:持有該對象的線程處於等待,讓出對象的控制權
  • notify()方法:通知正在等待這個對象控制權的線程可以繼續運行
  • notifyAll()方法:通知所有等待這個對象控制權的線程繼續運行

二.解釋說明

wait方法,有三個重載的方法:
- wait()
- wait(long time)
- wait(long time1,int time2)

1.wait()方法

wait方法將當前線程置入休眠狀態,知道被通知或中斷爲止,在調用wait()方法前,必須獲取對象級別鎖,因此它只能在同步方法和同步塊調用。當調用wait()方法,當前線程釋放鎖,在從wait()方法返回前,線程與其他線程競爭重新獲得鎖。


2.notify()方法

該方法也要在同步方法和同步塊中調用,在調用前必須獲得對象級別鎖,沒有則拋出異常。
該方法用來通知那些等待該對象的對象鎖的其他線程,如果有多個線程等待,則挑選出一個其中出於wait狀態的線程來發出通知,並使得它獲取對象鎖。(執行notify方法後,當前線程並不會馬上釋放該對象鎖,要等到程序退出synchronized代碼塊後,當前線程纔可以釋放對象鎖,處於wait狀態的線程纔可以獲取該對象鎖
下面舉個例子:

public class TestWatiNotify {
    public static Object obj=new Object();
    public static void main(String[] args){
        Thread1 t1=new Thread1();
        t1.setName("線程1");
        Thread2 t2=new Thread2();
        t2.setName("線程2");
        t1.start();
/*      try {
            Thread.sleep(100);
        }catch (InterruptedException e){
            e.printStackTrace();
        }*/
        t2.start();
    }
    static class Thread1 extends Thread{
        @Override
        public void run(){
            synchronized (obj){
                System.out.println("調用wait方法前");
                try{
                    obj.wait();
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("線程"+Thread.currentThread().getName()+"獲取到鎖");
            }
        }
    }
    static class Thread2 extends Thread{
        @Override
        public void run(){
            synchronized (obj){
                obj.notify();
                System.out.println("線程"+Thread.currentThread().getName()+"調用了notify方法");
            }
            System.out.println("線程"+Thread.currentThread().getName()+"釋放了該鎖");
            try{
                Thread.sleep(100);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("線程"+Thread.currentThread().getName()+"結束");
        }
    }
}

執行完上述代碼,出現下面的結果:

調用wait方法前
線程線程2調用了notify方法
線程線程2釋放了該鎖
線程線程1獲取到鎖
線程線程2結束

分析一下結果我們發現,首先是線程1獲取了對象鎖,然後執行了wait()方法,所以釋放了該對象鎖,線程2獲取了對象鎖,它調用了notify()方法,在執行完當前線程的同步塊後,線程1獲取到對象鎖,繼續執行線程1同步塊中wait方法之後的代碼,同時線程2也在同步塊後面的代碼。我們發現,線程在喚醒等待該對象的其他線程,並釋放掉對象鎖的時候,這時候對象出於空閒狀態,如果有多個出於等待的線程,那麼它們會競爭該對象鎖,但是不影響沒有加該對象鎖的線程執行。

3.notifyAll()方法

與notify()方法工作原理差不多,有一些小的差異:
notifyAll使所有原來在該對象上wait的線程退出wait狀態(但並非全部獲取對象鎖,它們會競爭,只會有一個線程獲取該對象鎖),在notifyAll線程退出當前的synchronized同步塊後,才參與競爭該對象鎖,如果有一個線程獲取到該對象鎖,它會繼續執行,直到執行完同步塊釋放對象鎖,其他的被喚醒的線程將繼續競爭對象鎖,一直進行下去,直到所有被喚醒的線程都執行完畢。

發佈了45 篇原創文章 · 獲贊 27 · 訪問量 26萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章