您現在的位置是:首頁 > 單機遊戲首頁單機遊戲

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

簡介現在我們已經知道了WeakHashMap是基於弱引用,其物件可能隨時被回收,適用於快取的場景

弱引用什麼時候被回收

這個問題是一個高頻面試題,本篇文章將從概念、原理、實際使用的角度來分析。希望對你有幫助:

一、什麼是WeakHashMap?

從名字可以得知主要和Map有關,不過還有一個Weak,我們就更能自然而然的想到這裡面還牽扯到一種弱引用結構,因此想要徹底搞懂,我們還需要知道四種引用。如果你已經知道了,可以跳過。

1、四種引用

在jvm中,一個物件如果不再被使用就會被當做垃圾給回收掉,判斷一個物件是否是垃圾,通常有兩種方法:引用計數法和可達性分析法。不管是哪一種方法判斷一個物件是否是垃圾的條件總是一個物件的引用是都沒有了。

JDK。1。2 之後,Java 對引用的概念進行了擴充,將引用分為了:強引用、軟引用、弱引用、虛引用4 種。而我們的WeakHashMap就是基於弱引用。

(1)強引用

如果一個物件具有強引用,它就不會被垃圾回收器回收。即使當前記憶體空間不足,JVM也不會回收它,而是丟擲 OutOfMemoryError 錯誤,使程式異常終止。比如String str = “hello”這時候str就是一個強引用。

(2)軟引用

記憶體足夠的時候,軟引用物件不會被回收,只有在記憶體不足時,系統則會回收軟引用物件,如果回收了軟引用物件之後仍然沒有足夠的記憶體,才會丟擲記憶體溢位異常。

(3)弱引用

如果一個物件具有弱引用,在垃圾回收時候,一旦發現弱引用物件,無論當前記憶體空間是否充足,都會將弱引用回收。

(4)虛引用

如果一個物件具有虛引用,就相當於沒有引用,在任何時候都有可能被回收。使用虛引用的目的就是為了得知物件被GC的時機,所以可以利用虛引用來進行銷燬前的一些操作,比如說資源釋放等。

我們的WeakHashMap是基於弱引用的,也就是說只要垃圾回收機制一開啟,就直接開始了掃蕩,看見了就清除。

2、為什麼需要WeakHashMap

WeakHashMap正是由於使用的是弱引用,因此它的物件可能被隨時回收。更直觀的說,當使用 WeakHashMap 時,即使沒有刪除任何元素,它的尺寸、get方法也可能不一樣。比如:

(1)呼叫兩次size()方法返回不同的值;第一次為10,第二次就為8了。

(2)兩次呼叫isEmpty()方法,第一次返回false,第二次返回true;

(3)兩次呼叫containsKey()方法,第一次返回true,第二次返回false;

(4)兩次呼叫get()方法,第一次返回一個value,第二次返回null;

是不是覺得有點噁心,這種飄忽不定的東西好像沒什麼用,試想一下,你準備使用WeakHashMap儲存一些資料,寫著寫著都沒了,那還儲存個啥呀。

不過有一種場景,最喜歡這種飄忽不定、一言不合就刪除的東西。那就是快取。在快取場景下,由於記憶體是有限的,不能快取所有物件,因此就需要一定的刪除機制,淘汰掉一些物件。

現在我們已經知道了WeakHashMap是基於弱引用,其物件可能隨時被回收,適用於快取的場景。下面我們就來看看,WeakHashMap是如何實現這些功能。

二、WeakHashMap工作原理

1、WeakHashMap為什麼具有弱引用的特點:隨時被回收物件

這個問題就比較簡單了,我們的目的主要是驗證。WeakHashMap是基於弱引用的,肯定就具有了弱引用的性質。我們去他的原始碼中看一下:

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

從這裡我們可以看到其內部的Entry繼承了WeakReference,也就是弱引用,所以就具有了弱引用的特點。不過還要注意一點,那就是ReferenceQueue,他的作用是GC會

清理掉物件之後,

引用物件會被放到ReferenceQueue中。

2、WeakHashMap中的Entry被GC後,WeakHashMap是如何將其移除的?

意思是某一個Entry突然被垃圾回收了,這之後WeakHashMap肯定就不能保留這個Entry了,那他是如何將其移除的呢?

WeakHashMap內部有一個expungeStaleEntries函式,在這個函式內部實現移除其內部不用的entry從而達到的自動釋放記憶體的目的。因此我們每次訪問WeakHashMap的時候,都會呼叫這個expungeStaleEntries函式清理一遍。這也就是為什麼前兩次呼叫WeakHashMap的size()方法有可能不一樣的原因。我們可以看看是如何實現的:

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

首先GC每次清理掉一個物件之後,引用物件會被放到ReferenceQueue中。然後遍歷這個queue進行刪除即可。

當然。WeakHashMap的增刪改查操作都會直接或者間接的呼叫expungeStaleEntries()方法,達到及時清除過期entry的目的。

三、WeakHashMap的使用

1、快取中使用

在文章一開始提到WeakHashMap可以在快取中使用。下面我們看一下如何使用的:

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

本案例來源於一個外國兄弟寫的,很棒。由於不能包含連結,因此會在評論區給出。

2、不要使用基礎型別作為WeakHashMap的key

快取的使用案例太多了,這裡舉一個WeakHashMap使用不規範的例子。

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

objectMap。put方法執行的時候i會被封裝為Integer型別的,Integer保留了-128到127的快取。但是對於int來說範圍大很多,因此那些Key <= 127的Entry將不會進行自動回收,但是那些大於127的將會被回收,因此最後的尺寸總是會穩定在128左右。

一文搞懂WeakHashMap工作原理(java後端面試高薪必備知識點)

OK。今天的文章先說到這。如有問題還請批評指正。目前名稱已由“java的架構師技術棧”改名為“愚公要移山”。感謝各位的支援。

一個人炫耀什麼,說明內心缺少什麼,我是愚公,要移山。

Top