亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中WeakHashMap的回收問題詳解

 更新時間:2023年09月07日 08:46:14   作者:幸平xp  
這篇文章主要介紹了Java中WeakHashMap的回收問題詳解,WeakHashMap弱鍵大致上是通過WeakReference和ReferenceQueue實現(xiàn),WeakHashMap的key是"弱鍵",即是WeakReference類型的,ReferenceQueue是一個隊列,它會保存被GC回收的"弱鍵",需要的朋友可以參考下

一、四大引用

在介紹WeakHashMap回收問題之前,我們要先介紹四大引用類型:

  • 強引用是最傳統(tǒng)的“引用”的定義,是指在程序代碼之中普遍存在的引用賦值,即類似“Object obj=new Object()”這種引用關系。無論任何情況下,只要強引用關系還存在,垃圾收集器就永遠不會回 收掉被引用的對象。
  • 軟引用是用來描述一些還有用,但非必須的對象。只被軟引用關聯(lián)著的對象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常前,會把這些對象列進回收范圍之中進行第二次回收,如果這次回收還沒有足夠的內(nèi)存, 才會拋出內(nèi)存溢出異常。在JDK 1.2版之后提供了SoftReference類來實現(xiàn)軟引用。
  • 弱引用也是用來描述那些非必須對象,但是它的強度比軟引用更弱一些,被弱引用關聯(lián)的對象只 能生存到下一次垃圾收集發(fā)生為止。當垃圾收集器開始工作,無論當前內(nèi)存是否足夠,都會回收掉只 被弱引用關聯(lián)的對象。在JDK 1.2版之后提供了WeakReference類來實現(xiàn)弱引用。
  • 虛引用也稱為“幽靈引用”或者“幻影引用”,它是最弱的一種引用關系。一個對象是否有虛引用的 存在,完全不會對其生存時間構(gòu)成影響,也無法通過虛引用來取得一個對象實例。為一個對象設置虛 引用關聯(lián)的唯一目的只是為了能在這個對象被收集器回收時收到一個系統(tǒng)通知。在JDK 1.2版之后提供 了PhantomReference類來實現(xiàn)虛引用。

對于本文主要涉及的為強引用,弱引用。其他引用本篇就不再多提了。 總結(jié)一下強引用與弱引用:

  • 強引用:主要為new出來的對象,就算內(nèi)存滿了,也不會回收它。因此當強引用過多時會導致OOM(內(nèi)存溢出),HashMap中key、value關系就為強引用。
  • 弱引用:被弱引用關聯(lián)的對象只 能生存到下一次垃圾收集發(fā)生為止,而WeakHashMap中的key,value就是弱引用關系。

二、WeakHashMap的回收問題

首先基本大概講述一下WeakHashMap弱鍵的原理:

大致上是通過WeakReference和ReferenceQueue實現(xiàn)的。WeakHashMap的key是“弱鍵”,即是WeakReference類型的;ReferenceQueue是一個隊列,它會保存被GC回收的“弱鍵”。

實現(xiàn)步驟是:

1、新建WeakHashMap,將“鍵值對”添加到WeakHashMap中。實際上,WeakHashMap是通過數(shù)組table保存Entry(鍵值對);每一個Entry實際上是一個單向鏈表,即Entry是鍵值對鏈表。

2、當某“弱鍵”不再被其它對象引用,并被GC回收時。在GC回收該“弱鍵”時,這個“弱鍵”也同時會被添加到ReferenceQueue(queue)隊列中。

3、 當下一次我們需要操作WeakHashMap時,會先同步table和queue。table中保存了全部的鍵值對,而queue中保存被GC回收的鍵值對;同步它們,就是刪除table中被GC回收的鍵值對。這就是“弱鍵”如何被自動從WeakHashMap中刪除的步驟了。和HashMap一樣,WeakHashMap是不同步的。可以使用 Collections.synchronizedMap 方法來構(gòu)造同步的 WeakHashMap。

讀者看到這可能還是比較抽象。沒關系,接下來我們直接上一些例子:

public static void main(String[] args) {
        WeakHashMap<String,String> weakMap = new WeakHashMap<>();
        weakMap.put("k1","v1");
        String k2 = new String("k2");
        weakMap.put(k2,"v2");
        weakMap.put(new String("k3"),"k3");
        System.out.println("weakMap回收前打印結(jié)果:");
        System.out.println(weakMap);
        // 因為WeakHashMap內(nèi)部維護的是一個弱引用映射所以gc直接回收
        System.gc();
        System.out.println("weakMap回收后打印結(jié)果:");
        System.out.println(weakMap);
    }

以上的打印結(jié)果是什么呢?

在這里插入圖片描述

可以看到打印結(jié)果是回收后的結(jié)果是只有k3的key-value被回收掉了。那么為什么呢?

這得首先從創(chuàng)建一個String對象說起,創(chuàng)建一個String對象最常見的有兩種情況:

// 第一種情況
String str1 = "a";
// 第二種情況
String str2 = new String("b");

對于第一種情況其對象的創(chuàng)建會先在字符串常量池判斷有沒有對應的字符串常量,如果沒有創(chuàng)建一個字符串常量一,然后將其引用指向在字符串常量池中的那個常量,如果存在則不需創(chuàng)建直接返回引用。 對于第二種情況其對象的引用還是會先在字符串常量池判斷有沒有對應的字符串常量,如果沒有創(chuàng)建一個字符串常量。 而后在堆中拷貝一個其字符串常量的對象,最后返回堆上的引用。

我畫了張圖對于情況二來講應該是這個:

在這里插入圖片描述

那么對于對象創(chuàng)建的引用我們了解了,那么接下來回到例子就很好理解。

  • 首先是 weakMap.put(“k1”,“v1”); 很明顯這里面是k1的引用是放在字符串常量池里的,是一種強引用。因此關于k1的key會一直保持下去。所以就是強引用,因此不會被gc。

然后則是:

String k2 = new String("k2");
weakMap.put(k2,"v2");

這里面的很明顯k2為new String的WeakHashMap外部的強引用因此k2的指針其實是在WeakHashMap外部被引用,所以不會被gc。如果要回收它也很容易,則只需要將其外部的引用k2置為null

String k2 = new String("k2");
weakMap.put(k2,"v2");
k2 = null;

而相對直接在WeakHashMap內(nèi)直接創(chuàng)建對象返回引用的話,那么很明顯就是弱鍵了。

weakMap.put(new String("k3"),"k3");

那么如何可以如何才能不回收這個字符串對象呢?我們剛剛畫圖提到了,我們可以用intern()方法返回其字符串常量池對應的對象

weakMap.put(new String("k3").intern(),"k3");

這個時候小伙伴可以自己去試一下,此時這個對象gc后也不會被回收了。就如同情況1:weakMap.put(“k1”,“v1”);

最后的最后附上完整代碼,有興趣的可以自己去試試:

public class MapGC {
    public static void main(String[] args) {
        WeakHashMap<String,String> weakMap = new WeakHashMap<>();
        weakMap.put("k1","v1");
        String k2 = new String("k2");
        weakMap.put(k2,"v2");
        weakMap.put(new String("k3"),"k3");
        System.out.println("weakMap回收前打印結(jié)果:");
        System.out.println(weakMap);
        // 因為WeakHashMap內(nèi)部維護的是一個弱引用映射所以gc直接回收
        System.gc();
        System.out.println("weakMap第一次回收后打印結(jié)果:");
        System.out.println(weakMap);
        k2 = null;
        weakMap.put(new String("k3").intern(),"k3");
        System.gc();
        System.out.println("weakMap第二次回收后打印結(jié)果:");
        System.out.println(weakMap);
    }
}

輸出結(jié)果:

在這里插入圖片描述

到此這篇關于Java中WeakHashMap的回收問題詳解的文章就介紹到這了,更多相關WeakHashMap回收內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論