日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

最简实例说明wait、notify、notifyAll的使用方法

發布時間:2025/3/21 编程问答 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 最简实例说明wait、notify、notifyAll的使用方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

/**

*? 轉載請注明作者longdick? ? http://longdick.iteye.com

*

*/

?

wait()、notify()、notifyAll()是三個定義在Object類里的方法,可以用來控制線程的狀態。

這三個方法最終調用的都是jvm級的native方法。隨著jvm運行平臺的不同可能有些許差異。

?

  • 如果對象調用了wait方法就會使持有該對象的線程把該對象的控制權交出去,然后處于等待狀態。
  • 如果對象調用了notify方法就會通知某個正在等待這個對象的控制權的線程可以繼續運行。
  • 如果對象調用了notifyAll方法就會通知所有等待這個對象控制權的線程繼續運行。

?

其中wait方法有三個over load方法:

wait()

wait(long)

wait(long,int)

wait方法通過參數可以指定等待的時長。如果沒有指定參數,默認一直等待直到被通知。

?

?

以下是一個演示代碼,以最簡潔的方式說明復雜的問題:

簡要說明下:

NotifyThread是用來模擬3秒鐘后通知其他等待狀態的線程的線程類;

WaitThread是用來模擬等待的線程類;

等待的中間對象是flag,一個String對象;

main方法中同時啟動一個Notify線程和三個wait線程;

?

?

Java代碼??
  • public?class?NotifyTest?{??
  • ????private??String?flag?=?"true";??
  • ??
  • ????class?NotifyThread?extends?Thread{??
  • ????????public?NotifyThread(String?name)?{??
  • ????????????super(name);??
  • ????????}??
  • ????????public?void?run()?{???????
  • ????????????try?{??
  • ????????????????sleep(3000);//推遲3秒鐘通知??
  • ????????????}?catch?(InterruptedException?e)?{??
  • ????????????????e.printStackTrace();??
  • ????????????}??
  • ??????????????
  • ????????????????flag?=?"false";??
  • ????????????????flag.notify();??
  • ????????}??
  • ????};??
  • ??
  • ????class?WaitThread?extends?Thread?{??
  • ????????public?WaitThread(String?name)?{??
  • ????????????super(name);??
  • ????????}??
  • ??
  • ????????public?void?run()?{??
  • ??????????????
  • ????????????????while?(flag!="false")?{??
  • ????????????????????System.out.println(getName()?+?"?begin?waiting!");??
  • ????????????????????long?waitTime?=?System.currentTimeMillis();??
  • ????????????????????try?{??
  • ????????????????????????flag.wait();??
  • ????????????????????}?catch?(InterruptedException?e)?{??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ????????????????????waitTime?=?System.currentTimeMillis()?-?waitTime;??
  • ????????????????????System.out.println("wait?time?:"+waitTime);??
  • ????????????????}??
  • ????????????????System.out.println(getName()?+?"?end?waiting!");??
  • ??????????????
  • ????????}??
  • ????}??
  • ??
  • ????public?static?void?main(String[]?args)?throws?InterruptedException?{??
  • ????????System.out.println("Main?Thread?Run!");??
  • ????????NotifyTest?test?=?new?NotifyTest();??
  • ????????NotifyThread?notifyThread?=test.new?NotifyThread("notify01");??
  • ????????WaitThread?waitThread01?=?test.new?WaitThread("waiter01");??
  • ????????WaitThread?waitThread02?=?test.new?WaitThread("waiter02");??
  • ????????WaitThread?waitThread03?=?test.new?WaitThread("waiter03");??
  • ????????notifyThread.start();??
  • ????????waitThread01.start();??
  • ????????waitThread02.start();??
  • ????????waitThread03.start();??
  • ????}??
  • ??
  • }??
  • ?

    OK,如果你拿這段程序去運行下的話, 會發現根本運行不了,what happened?滿屏的java.lang.IllegalMonitorStateException。

    沒錯,這段程序有很多問題,我們一個個來看。

    ?

    首先,這兒要非常注意的幾個事實是

    ?

  • 任何一個時刻,對象的控制權(monitor)只能被一個線程擁有。
  • 無論是執行對象的wait、notify還是notifyAll方法,必須保證當前運行的線程取得了該對象的控制權(monitor)
  • 如果在沒有控制權的線程里執行對象的以上三種方法,就會報java.lang.IllegalMonitorStateException異常。
  • JVM基于多線程,默認情況下不能保證運行時線程的時序性
  • ?

    基于以上幾點事實,我們需要確保讓線程擁有對象的控制權。

    也就是說在waitThread中執行wait方法時,要保證waitThread對flag有控制權;

    在notifyThread中執行notify方法時,要保證notifyThread對flag有控制權。

    ?

    線程取得控制權的方法有三:

    ?

  • 執行對象的某個同步實例方法。
  • 執行對象對應類的同步靜態方法。
  • 執行對該對象加同步鎖的同步塊。
  • 我們用第三種方法來做說明: 將以上notify和wait方法包在同步塊中 Java代碼??
  • synchronized?(flag)?{??
  • ????????????????flag?=?"false";??
  • ????????????????flag.notify();??
  • ????????????}??
  • ?

    ?

    Java代碼??
  • synchronized?(flag)?{??
  • ????????????????while?(flag!="false")?{??
  • ????????????????????System.out.println(getName()?+?"?begin?waiting!");??
  • ????????????????????long?waitTime?=?System.currentTimeMillis();??
  • ????????????????????try?{??
  • ????????????????????????flag.wait();??
  • ????????????????????}?catch?(InterruptedException?e)?{??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ????????????????????waitTime?=?System.currentTimeMillis()?-?waitTime;??
  • ????????????????????System.out.println("wait?time?:"+waitTime);??
  • ????????????????}??
  • ????????????????System.out.println(getName()?+?"?end?waiting!");??
  • ????????????}??
  • ?

    我們向前進了一步。

    問題解決了嗎?

    好像運行還是報錯java.lang.IllegalMonitorStateException。what happened?

    ?

    這時的異常是由于在針對flag對象同步塊中,更改了flag對象的狀態所導致的。如下:

    flag="false";

    flag.notify();

    對在同步塊中對flag進行了賦值操作,使得flag引用的對象改變,這時候再調用notify方法時,因為沒有控制權所以拋出異常。

    ?

    我們可以改進一下,將flag改成一個JavaBean,然后更改它的屬性不會影響到flag的引用。

    我們這里改成數組來試試,也可以達到同樣的效果:

    ?

    ?

    Java代碼??
  • private???String?flag[]?=?{"true"};??
  • ?

    ?

    Java代碼??
  • synchronized?(flag)?{??
  • ????????????flag[0]?=?"false";??
  • ????????????flag.notify();??
  • ????????}??
  • ?

    ?

    Java代碼??
  • synchronized?(flag)?{??
  • ????????????????while?(flag[0]!="false")?{??
  • ????????????????????System.out.println(getName()?+?"?begin?waiting!");??
  • ????????????????????long?waitTime?=?System.currentTimeMillis();??
  • ????????????????????try?{??
  • ????????????????????????flag.wait();??
  • ??????????????????????????
  • ????????????????????}?catch?(InterruptedException?e)?{??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ?

    ?

    這時候再運行,不再報異常,但是線程沒有結束是吧,沒錯,還有線程堵塞,處于wait狀態。

    ?

    原因很簡單,我們有三個wait線程,只有一個notify線程,notify線程運行notify方法的時候,是隨機通知一個正在等待的線程,所以,現在應該還有兩個線程在waiting。

    ?

    我們只需要將NotifyThread線程類中的flag.notify()方法改成notifyAll()就可以了。notifyAll方法會通知所有正在等待對象控制權的線程。

    ?

    最終完成版如下:

    ?

    ?

    Java代碼??
  • public?class?NotifyTest?{??
  • ????private?String?flag[]?=?{?"true"?};??
  • ??
  • ????class?NotifyThread?extends?Thread?{??
  • ????????public?NotifyThread(String?name)?{??
  • ????????????super(name);??
  • ????????}??
  • ??
  • ????????public?void?run()?{??
  • ????????????try?{??
  • ????????????????sleep(3000);??
  • ????????????}?catch?(InterruptedException?e)?{??
  • ????????????????e.printStackTrace();??
  • ????????????}??
  • ????????????synchronized?(flag)?{??
  • ????????????????flag[0]?=?"false";??
  • ????????????????flag.notifyAll();??
  • ????????????}??
  • ????????}??
  • ????};??
  • ??
  • ????class?WaitThread?extends?Thread?{??
  • ????????public?WaitThread(String?name)?{??
  • ????????????super(name);??
  • ????????}??
  • ??
  • ????????public?void?run()?{??
  • ????????????synchronized?(flag)?{??
  • ????????????????while?(flag[0]?!=?"false")?{??
  • ????????????????????System.out.println(getName()?+?"?begin?waiting!");??
  • ????????????????????long?waitTime?=?System.currentTimeMillis();??
  • ????????????????????try?{??
  • ????????????????????????flag.wait();??
  • ??
  • ????????????????????}?catch?(InterruptedException?e)?{??
  • ????????????????????????e.printStackTrace();??
  • ????????????????????}??
  • ????????????????????waitTime?=?System.currentTimeMillis()?-?waitTime;??
  • ????????????????????System.out.println("wait?time?:"?+?waitTime);??
  • ????????????????}??
  • ????????????????System.out.println(getName()?+?"?end?waiting!");??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??
  • ????public?static?void?main(String[]?args)?throws?InterruptedException?{??
  • ????????System.out.println("Main?Thread?Run!");??
  • ????????NotifyTest?test?=?new?NotifyTest();??
  • ????????NotifyThread?notifyThread?=?test.new?NotifyThread("notify01");??
  • ????????WaitThread?waitThread01?=?test.new?WaitThread("waiter01");??
  • ????????WaitThread?waitThread02?=?test.new?WaitThread("waiter02");??
  • ????????WaitThread?waitThread03?=?test.new?WaitThread("waiter03");??
  • ????????notifyThread.start();??
  • ????????waitThread01.start();??
  • ????????waitThread02.start();??
  • ????????waitThread03.start();??
  • ????}??
  • ??
  • } ?

  • from:?http://longdick.iteye.com/blog/453615

    總結

    以上是生活随笔為你收集整理的最简实例说明wait、notify、notifyAll的使用方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。