1. 程式人生 > >java線程學習之notify方法和notifyAll方法

java線程學習之notify方法和notifyAll方法

except 代碼 代碼塊 monitor 無法 獲得 選擇 tee 監視

notify(通知)方法,會將等待隊列中的一個線程取出。比如obj.notify();那麽obj的等待隊列中就會有一個線程選中並且喚醒,然後被喚醒的隊列就會退出等待隊列。活躍線程調用等待隊列中的線程時,因為現在的活躍線程還用有鎖,會先將synchronized代碼塊執行完畢,釋放對象監視器,被喚醒的線程才會獲得這個監視器,然後被喚醒的線程才能繼續執行。也就是說原來在等待隊列中的線程被喚醒後,在被執行notify的一瞬間並不會立刻執行,因為在被執行notify的一瞬間,原來執行notify的線程還持有著鎖,所以其他線程還無法獲取這個實例的鎖。

舉個例子:假設熊大和熊二都要到小黑屋裏面壁十分鐘,小黑屋同一時刻只能允許一只熊進行面壁思過。熊大先進開始面壁思過同時把門鎖上(相當於執行synchronized代碼塊擁有鎖),結果在熊大面壁到三分鐘的時候,困了想去睡覺(相當於執行wait()方法,進去到等待隊列),這時它走出了門(相當於釋放鎖)去睡覺,熊二開始進來進行面壁思過,當熊二面壁到6分鐘的時候,喊了一聲讓熊大接著來面壁思過(相當於執行notify方法),因為熊二還在繼續面壁思過,所以熊大要在小黑屋外一直等,等到熊二面壁結束後(釋放了鎖),才能進去接著面壁,面壁剩余的七分鐘,所以說即使熊二在第6分鐘叫醒了熊大,但因為此時熊二在小黑屋裏,熊大也不可能第一時間面壁思過。

如果說等待隊列中的線程不止一個,那麽當執行notify的時候叫醒那一個呢,被喚醒的線程是隨機選擇的。那麽被喚醒的線程在作為鎖定此對象的下一個線程方面沒有可靠的特權或劣勢。

notifyAll(通知全部)方法是將等待隊列中的所以線程都喚醒,用法和notify一樣。區別是notify只能喚醒等待隊列中的一個,而notifyAll卻能喚醒等待隊列中的全部。

在實際使用時,是使用notify還是notifyAll,那個更好呢。

因為notify喚醒的線程比notifyAll少,所以notify的處理速度會更快。

使用notifyAll的代碼要比使用notify的代碼更健壯,因為使用notify如果處理不好,程序便有可能終止。

wait() ,notify()和notifyAll()方法都要獲得此對象的監視器,也就是要獲得鎖,否則會報IllegalMonitorStateException異常

java線程學習之notify方法和notifyAll方法