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

歡迎訪問 生活随笔!

生活随笔

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

java

WeakHashMap和Java引用类型详细解析

發布時間:2023/12/9 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WeakHashMap和Java引用类型详细解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

WeakHashMap是種弱引用的HashMap,這是說,WeakHashMap里的key值如果沒有外部強引用,在垃圾回收之后,WeakHashMap的對應內容也會被移除掉。

1.1?Java的引用類型

在講解WeakHashMap之前,我們需要了解Java中引用的相關類:

ReferenceQueue,引用隊列,與某個引用類綁定,當引用死亡后,會進入這個隊列。

HardReference,強引用,任何以類似String str=new String()建立起來的引用,都是強引用。在str指向另一個對象或者null之前,該String對象都不會被GC(Garbage Collector垃圾回收器)回收;

WeakReference,弱引用,可以通過java.lang.ref.WeakReference來建立,當GC要求回收對象時,它不會阻止對象被回收,該對象會立刻被回收;

SoftReference,軟引用,可以通過java.lang.ref.SoftReference來建立,和弱引用一樣,當GC要求回收時,它不會阻止對象被回收,但不同的是該對回收過程會被延遲,必須要等到JVM heap內存不夠用,接近產生OutOfMemory錯誤時,才會回收;

PhantomReference,虛引用,可以通過java.lang.ref.PhantomPeference來建立,這種類型的引用很特別,大多數時間,無法通過它拿到其引用的對象,但是,當這個對象死亡的時候,該引用還是會進入ReferenceQueue隊列。

下面提供一個例子來分別說明它們的作用:

ReferenceQueue<Ref> queue?= new?ReferenceQueue<Ref>();

// 創建一個弱引用

WeakReference<Ref> weak?= new?WeakReference<Ref>(new?Ref("Weak"),queue);

// 創建一個虛引用

PhantomReference<Ref> phantom?= new?PhantomReference<Ref>(new?Ref(

"Phantom"), queue);

// 創建一個軟引用

SoftReference<Ref> soft?= new?SoftReference<Ref>(new?Ref("Soft"),queue);

?

System.out.println("引用內容:");

System.out.println(weak.get());

System.out.println(phantom.get());

System.out.println(soft.get());

?

System.out.println("被回收的引用:");

for?(Reference?r?= null; (r?= queue.poll()) != null;) {

System.out.println(r);

}

?

Ref這個類是個自定義的測試類,源碼如下所示:

class?Ref {

Object v;

Ref(Object v) {

this.v?= v;

}

public?String toString() {

return?this.v.toString();

}

}

?

在這個例子里,分別創建了弱引用、虛引用和軟引用,get()方法用于獲取它們引用的Ref對象,可以注意到,Ref對象在外部并沒有任何引用,所以,在某個時間點,GC應當會回收對象。來看看代碼執行的結果:

引用內容:

Weak

null

Soft

被回收的引用:

可以看到,弱引用和軟引用的對象還是可達的,但是虛引用是不可達的。被回收的引用沒有內容,說明GC還沒有回收它們。

這證實了虛引用的性質

虛引用非常弱,以至于它自己也找不到自己的引用內容。

對之前的代碼進行改造,在輸出內容前加入代碼:

// 強制垃圾回收

System.gc();

再執行一次,得到結果:

引用內容:

null

null

Soft

被回收的引用:

java.lang.ref.WeakReference@3b764bce

java.lang.ref.PhantomReference@759ebb3d

現在可達的引用只剩下Soft了,引用隊列里多出了兩條引用,說明WeakReference和PhantomReference的對象被回收。

再修改一次代碼,讓WeakPeference和PhantomReference去引用一個強引用對象:

Ref wr?= new?Ref("Hard");

WeakReference<Ref> weak?= new?WeakReference<Ref>(wr, queue);

PhantomReference<Ref> phantom?= new?PhantomReference<Ref>(wr, queue);

輸出結果如下所示:

引用內容:

Hard

null

Soft

被回收的引用:

這證實了弱引用的性質

弱引用的對象,如果沒有被強引用,在垃圾回收后,引用對象會不可達。

?

1.2?WeakHashMap實現方式

WeakHashMap利用了ReferenceQueue和WeakReference來實現它的核心功能:當key值沒有強引用的時候,從WeakHashMap里移除。

先來看看WeakHashMap的鍵值對實體類WeakHashMap.Entry的實現:

?private?static?class?Entry<K,V> extends?WeakReference<Object> implements?Map.Entry<K,V> {

????????Entry(Object key, V value,

??????????????ReferenceQueue<Object> queue,

??????????????int?hash, Entry<K,V> next) {

????????????super(key, queue);

????????????this.value?= value;

????????????this.hash??= hash;

????????????this.next??= next;

????????}

????...

}

關鍵注意兩處:

1、Entry繼承自WeakReference;

2、Entry本身沒有保存key值,而是把key作為WeakReference的引用對象交給了super構造。

這說明,Entry是個針對key值的弱引用。

WeakHashMap實現清除陳舊實體的方法是expungStaleEntries(),其源碼實現如下:

private?void?expungeStaleEntries() {

????//遍歷引用隊列,找到每一個被GC收集的對象

????????for?(Object x; (x?= queue.poll()) != null; ) {

????????????synchronized?(queue) {

????????????????@SuppressWarnings("unchecked")

????????????????????Entry<K,V> e?= (Entry<K,V>) x;

????????????????int?i?= indexFor(e.hash, table.length);

????????????????//從鏈表里移除該實體

????????????????Entry<K,V> prev?= table[i];

????????????????Entry<K,V> p?= prev;

????????????????while?(p?!= null) {

????????????????????Entry<K,V> next?= p.next;

????????????????????if?(p?== e) {

????????????????????????if?(prev?== e)

????????????????????????????table[i] = next;

????????????????????????else

????????????????????????????prev.next?= next;

????????????????????????//幫助GC執行

????????????????????????e.value?= null;

????????????????????????size--;

????????????????????????break;

????????????????????}

????????????????????prev?= p;

????????????????????p?= next;

????????????????}

????????????}

????????}

????}

?

expungStaleEntries()方法會在resize、put、get、forEach方法里被調用。

總結

以上是生活随笔為你收集整理的WeakHashMap和Java引用类型详细解析的全部內容,希望文章能夠幫你解決所遇到的問題。

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