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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java对象实习

發布時間:2023/12/3 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java对象实习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java將出現在源代碼中的字符串競爭者存儲在池中。 換句話說,當您有如下代碼時:

String a = "I am a string"; String b = "I am a string";

變量a和b將具有相同的值。 不只是兩個相等的字符串,而是完全相同的字符串。 用Java單詞a == b是正確的。 但是,這僅適用于字符串以及較小的整數和長值。 其他對象不會被插入,因此,如果您創建兩個具有完全相同值的對象,它們通常是不相同的。 它們可能并且可能相等,但對象不同。 有時候這可能很麻煩。 可能是當您從某個持久性存儲中獲取某個對象時。 如果您碰巧多次獲取同一對象,則可能希望獲取同一對象而不是兩個副本。 換句話說,我也可以說您只希望在持久性中的單個對象的內存中擁有一個副本。 一些持久層可以為您完成此任務。 例如,JPA實現遵循此模式。 在其他情況下,您可能需要自己執行緩存。

在這個示例中,我將描述一個簡單的內部池實現,也可以在stackoverflow主題上進行查看。 在本文中,我還將解釋導致此處(以及此處)描述的解決方案的細節和注意事項。 本文包含的礦石信息比原始討論要多。

對象池

實習需要一個對象池。 當您有一個對象并且想要實習該對象時,您實際上是在對象池中查看以查看是否已經有一個對象等于手頭的對象。 如果有一個,我們將使用已經存在的一個。 如果沒有對象等于實際對象,則將實際對象放入池中,然后使用該對象。

在實施過程中,我們必須面對兩個主要問題:

  • 垃圾收集
  • 多線程環境

如果不再需要某個對象,則必須將其從池中刪除。 刪除可以由應用程序完成,但這將是完全過時且古老的方法。 Java優于C ++的主要優勢之一是垃圾回收。 我們可以讓GC收集這些對象。 為此,我們不應該在對象池中強烈引用池中的對象。

參考

如果您知道什么是軟引用,弱引用和幻像引用,請跳至下一部分。

您可能會注意到,我并不是簡單地說“參考”,而是說“強參考”。 如果您了解到在沒有對對象的引用時GC會收集對象,則它不是絕對正確的。 事實上,這是GC處理不可觸摸對象所需的強大參考。 為了更精確,強引用應該可以與其他強引用一起從局部變量,靜態字段和類似的普遍位置傳播。 換句話說:(強)引用從一個死亡對象指向另一個死亡對象的點不計算在內,它們將一起被刪除并收集。

因此,如果這些都是強引用,那么您可能不會想到這么強的引用。 你是對的。 有一個名為java.lang.ref.Reference的類,還有另外三個擴展它的類。 這些類是:

  • PhantomReference
  • WeakReference和
  • SoftReference
  • 在同一包中。 如果閱讀文檔,您可能會懷疑我們所需要的只是薄弱的一環。 幻影在池中使用毫無疑問,因為幻影引用不能用于訪問對象。 軟引用太過分了。 如果沒有對該對象的強引用,那么將其保留在池中就沒有意義。 如果它再次來自某個來源,我們將再次實習。 這肯定是一個不同的實例,但是沒有人注意到它,因為沒有引用前一個實例。

    弱引用是可以用于訪問對象但不會改變GC行為的引用。

    WeakHashMap

    弱引用不是我們必須直接使用的類。 有一個名為WeakHashMap的類,該類使用軟引用來引用關鍵對象。 這實際上是我們所需要的。 當我們實習一個對象并想查看它是否已經在池中時,我們搜索所有對象以查看是否有任何對象等于實際對象。 地圖就是實現此搜索功能的東西。 在弱引用中持有密鑰只會讓GC在沒人需要時收集密鑰對象。

    到目前為止我們可以搜索,這很好。 使用地圖,我們還必須獲得一些價值。 在這種情況下,我們只想獲取相同的對象,因此必須在不存在該對象的情況下將其放入地圖中。 但是,將對象本身放置在那里會破壞我們獲得的結果,即我們僅保留對同一對象的弱引用作為鍵。 我們必須創建并弱引用該對象作為鍵。

    弱水池

    在那之后的解釋是代碼。 它只是說如果有一個對象等于實際對象,那么get(actualObject)應該返回它。 如果沒有,則get(actualObject)將返回null。 方法put(newObject)將一個新對象放入池中,如果有一個等于新對象的對象,它將用新對象覆蓋舊對象的位置。

    public class WeakPool<T> {private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();public T get(T object){final T res;WeakReference<T> ref = pool.get(object);if (ref != null) {res = ref.get();}else{res = null;}return res;}public void put(T object){pool.put(object, new WeakReference<T>(object));} }

    實習生池

    解決該問題的最終方法是一個內部池,該池很容易使用已有的WeakPool來實現。 InternPool內部有一個弱池,并且intern(T object)只有一個同步方法。

    public class InternPool<T> {private final WeakPool<T> pool = new WeakPool<T>();public synchronized T intern(T object) {T res = pool.get(object);if (res == null) {pool.put(object);res = object;}return res;} }

    該方法嘗試從池中獲取對象,如果該對象不存在,則將其放在那里,然后將其返回。 如果已經有一個匹配的對象,那么它將返回池中已經存在的對象。

    多線程

    該方法必須同步以確保新對象的檢查和插入是原子的。 如果沒有同步,則可能發生兩個線程檢查池中兩個相等的實例,兩個線程都發現其中沒有匹配的對象,然后將其版本插入池中。 其中一個,后來放置其對象的對象將是贏家,它會覆蓋已存在的對象,但較寬松的人也認為它擁有真正的單個對象。 同步解決了這個問題。

    與垃圾收集器賽車

    即使使用該池的java應用程序的不同線程不會在同時使用該池時遇到麻煩,但是如果對垃圾收集器線程有任何干擾,我們仍然應該查看它。

    調用弱引用get方法時,引用可能返回null。 當垃圾回收器回收了關鍵對象,但是弱輪詢實現中的弱哈希映射仍然沒有刪除條目時,就會發生這種情況。 即使弱映射實現每次查詢映射時都檢查密鑰的存在,它也可能發生。 垃圾收集器可以在通話之間踢get()弱哈希映射,并號召get()來返回的弱引用。 哈希映射返回對對象的引用,該對象在返回時就已經存在,但是由于該引用是弱引用,因此將其刪除,直到我們的Java應用程序執行到下一條語句為止。

    在這種情況下, WeakPool實現將返回null。 沒問題。 InternPool也不InternPool困擾。

    如果查看前面提到的stackoverflow主題中的其他代碼,則可以看到一個代碼:

    public class InternPool<T> {private WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();public synchronized T intern(T object) {T res = null;// (The loop is needed to deal with race// conditions where the GC runs while we are// accessing the 'pool' map or the 'ref' object.)do {WeakReference<T> ref = pool.get(object);if (ref == null) {ref = new WeakReference<T>(object);pool.put(object, ref);res = object;} else {res = ref.get();}} while (res == null);return res;} }

    在此代碼中,作者創建了一個無限循環來處理這種情況。 不太吸引人,但是有效。 該循環不可能無限期地執行。 可能不超過兩次。 構造很難理解,很復雜。 士氣:單一責任原則。 專注于簡單的事情,將您的應用程序分解為簡單的組件。

    結論

    即使Java僅對String進行實習,并且某些裝箱原始類型的對象也可能進行實習,有時也希望進行實習。 在這種情況下,實習不是自動的,應用程序必須明確執行它。 通過將復制粘貼粘貼到代碼庫中,可以使用此處列出的兩個簡單類來實現此目的,或者可以:

    <dependency><groupId>com.javax0</groupId><artifactId>intern</artifactId><version>1.0.0</version> </dependency>

    從Maven中央插件導入庫作為依賴項。 該庫是最小的,僅包含這兩個類,可在Apache許可下使用。 該庫的源代碼在GitHub上 。

    參考: Java Deep博客上來自我們JCG合作伙伴 Peter Verhas的Java Object Interning。

    翻譯自: https://www.javacodegeeks.com/2014/03/java-object-interning.html

    總結

    以上是生活随笔為你收集整理的Java对象实习的全部內容,希望文章能夠幫你解決所遇到的問題。

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