2017-03-28 69 views
3

最近,我在採訪中被問及爲什麼使用wait,notifynotifyAll。我解釋了他們。爲什麼等待,通知和notifyAll是Object類中的方法不像Cloneable

之後,他們讓我假設一個應用程序總是單線程的。它真的需要嗎?我的回答是否定的。

然後,他們問爲什麼設計像wait,notifynotifyAllObject類的方法。爲什麼Java沒有接口,並且這些方法在該接口中,以及哪個類想要實現它可以使用它。所以,我有點卡住,無法思考這個設計。任何人都可以請播種嗎?

+0

爲什麼當它們已經實施時實施它們? – user2717954

+0

wait/notify/notifyAll已被重構爲[接口](https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/locks/Condition.html) 。另請參閱[這篇文章](http://stackoverflow.com/questions/4912165/whats-the-best-alternative-to-wait-notify-for-low-level-synchronization) –

+0

可能重複的[爲什麼是等待( )和notify()在Java的對象類聲明?](http://stackoverflow.com/questions/1769489/why-are-wait-and-notify-declared-in-javas-object-class) –

回答

2

JVM使用OS級別的線程。這意味着每個具體OS的每個具體JVM都以不同的方式處理線程。而這些方法不僅在Object類中實現,它們被標記爲native,這種方式意味着在JVM的系統層中實現。

如果這些方法在某個接口中,那意味着任何人都可以重新定義它們。

0

Wait and notify和notifyAll不僅僅是普通的方法或同步工具,更重要的是它們是Java中兩個線程之間的通信機制。如果這種機制不能通過像關鍵字這樣的java關鍵字獲得,那麼Object類是正確的地方,以使它們可用於每個對象。記住同步和等待通知是兩個不同的區域,不要混淆它們是相同的或相關的。同步是爲了提供互斥,確保Java類的線程安全性,例如競爭狀態,而wait和notify是兩個線程之間的通信機制。

0

然後,他們問我爲什麼是設計像waitnotifynotifyAll都在Object類的方法。爲什麼Java沒有接口,並且這些方法在該接口中,以及哪個類想要實現它可以使用它。

所有這些方法都是在本地代碼中實現的,並且它們與​​塊緊密集成,並將它們封裝起來。它們是Java語言定義的一部分,具有程序員依賴的特定行爲。他們不適合任何對象實現的接口方法。

當一個對象在另一個對象上調用obj.wait();時,它不必擔心wait的實現。它需要確保它具有該對象上的互斥鎖,以便可以對其進行重要更新或其他存儲,並且如果對象本身實現了wait方法,那麼該對象可能違反語言要求,例如,允許多個線程同時進入受保護的塊。一個線程可以synchronize並在另一個對象上調用wait/notify/notifyAll而不必擔心該對象是否已經適當地實現了這些方法。通過在Object上製作它們final方法,無論對象類型或本地實現如何,該行爲都可以工作。

而且,如我所提到的,wait/notify/notifyAll都與周圍​​塊集成。當線程在wait()中被阻塞時,將釋放周圍的​​鎖,以便其他線程可以訪問受保護的塊。如果wait()只是一個沒有其他奇怪語言特徵的簡單方法調用,則不可能進行此協調。

這讓我想起我的其他的答案在這裏:Concept behind putting wait(),notify() methods in Object class

+0

我會說,至少在編譯器圈中 - 至少在編譯器圈中的共識是允許每個對象用於同步是一個代價高昂的錯誤,特別是考慮到同步的最佳實踐(使用最終對象來確保鎖不能泄漏)。對於提供顯式鎖類沒有太多好的理由(一個接口確實是一個奇怪的選擇,因爲只有有限的可擴展性是有道理的)才能真正實現這些特性。你不同意嗎? – Voo

+0

對不起,但我不同意。如果你不需要使用它,它如何「昂貴」?當我希望JVM能夠有效地支持它時,每個人都是如此反「同步」 - 也許使用人們想要手動完成的相同的'Lock'對象。我想編寫和維護更少的代碼,並教我的初級程序員直接使用語言特性,而不是直接使用'Lock'對象,除非我必須使用@Voo。 – Gray

+0

由於JVM必須爲每個對象支持對象頭中的鎖,儘管只有0.0..01%的對象實際上會使用它。現在,HotSpot特別花費了很大的精力來儘量減少相關的開銷,但是這種複雜性本身就會帶來成本:代碼的那部分存在許多錯綜複雜的錯誤。 – Voo

0

它從一開始就是Java程序將是多線程的設計目標。記住這個計劃是爲了讓Java減少嵌入式編程的威脅,整個服務器端網絡應用的事情(導致Sun核心業務的商品化)是一個意外。

由於目標是創建可與其他設備交互的嵌入式應用程序,因此它必須是多線程的,才能實現網絡友好和事件驅動。但是編寫高效的多線程服務器在java的列表中並不高。

Java很長一段時間沒有ReentrantLock或非阻塞I/O。最初可用的主要數據結構是Vector,Hashtable和StringBuffer(所有這些都在所有公共方法上同步)。從這個選擇看來,這個目標似乎足夠好,而不是儘可能高效。後來很明顯,Java需要對服務器應用程序的用例更高效,1.2引入了未同步的Vector和Hashtable的等價物。這看起來像是一種事後的想法,一旦顯然Java有了一個它以前沒有設計過的新角色,就可以進行一次課程調整。

如果Java留在小生境中,那麼可能內在的鎖已經足夠。看起來最初的計劃只是針對內部鎖,因此鎖可能會連接到對象。

相關問題