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

2020-12-03 愚公要移山1

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

一、什麼是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是基於弱引用的,肯定就具有了弱引用的性質。我們去他的源碼中看一下:

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

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

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

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

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

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

三、WeakHashMap的使用

1、緩存中使用

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

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

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

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

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

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

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

相關焦點

  • Java程式設計師需要什麼學歷才能找到工作?學歷低怎麼辦?
    很多人應該都聽說過一句話:學歷代表不了什麼,只要技術好,小學學歷也可以很多人在聽到這句話後,就毅然決然的衝進IT行業,通過培訓等等途徑,想要進入這個行業拿高薪,然而現實又是那麼的殘酷,這些學歷低的人往往是花了不少錢最終還落得個找不到工作的下場為什麼會這樣?
  • 後端工程師,必須搞懂的 RPC 框架
    去年我面試一位高級後端工程師的時候,看他簡歷上寫著「熟練掌握 RPC 框架」,所以我就試探著問了他幾個原理方面的問題,比如,「大概說下 RPC 框架的核心原理」「、描述下序列化部分的邏輯」。但聊了半天,我發現他其實並不熟,他的回答基本都是在告訴我怎麼用,以及怎麼更好地用好這些框架。
  • 搞定HashMap面試,深入講解HashMap的工作原理
    摘要:HashMap是近幾年java面試新秀,出場率高達80%以上,如此高頻的出場不得不讓碼農們慎重其事。但依舊拜倒在它的石榴裙下,讓面試場面一度尷尬。它也是開發中最常用到的key-value數據類型。
  • Java面試高頻考點:反射機制使用大全
    作為一個Java開發工程師,在面試的過程中,反射機制也是經常會被問到的一個問題。例如Spring的IOC實現機制,其底層都是依賴於java的反射機制,因此,這是一個非常重要的知識點。對於初學java的同學來說,掌握其使用方法很有必要。
  • Java集合框架——面試必備
    (6)HashMapHashMap基於hashing原理,通過put()和get()方法存儲和獲取對象。當我們將鍵值對傳遞給put()方法時,它調用建對象的hashCode()方法來計算hashCode值,然後找到bucket位置來儲存值對象。當獲取對象時,通過建對象的equals()方法找到正確的鍵值對,然後返回對象。
  • Java初學者進階系列:HashMap的容量與性能
    (HashMap是常見的數據結構,也是面試和工作中常用到的數據結構,線下可以使用微通過crazy042438一起單點討論)1.1 Initial Capacity與Load FactorInitial Capacity:初始化容量,它表示HashMap底層的那個數組,也就是Entry數組有多長,這個值默認是16。
  • 支付寶高級Java現場面試37題:頁鎖+死鎖+集群+雪崩+負載等
    2020-09-26 15:45:21 來源: java架構codi 舉報
  • JAVA專業術語面試100問
    前言:面試技巧另外開篇再說,先上面試乾貨吧。Redis、消息隊列、SQL不要走開,關注後更精彩!1、面向對象的特點有哪些?26、描述類加載器工作機制?27、分別寫出堆內存溢出與棧內存溢出的程序?28、Java 8 內存模型進行了哪些改進?29、簡述java內存分配與回收策率以及Minor GC和Major GC?
  • 40張動圖搞懂99%的泵原理,技術人必備
    16、雙動往復泵工作原理40、葉片泵工作原理3、為何公司寧願高薪招新人,也不願加薪留老員工?4、化工人必備 |《石油化工設計手冊》(5本)最新版5、免費領取丨《化工工藝設計手冊》(第四版)上、下冊
  • 985碩,秋招面試30家企業,怒斬阿里、字節、美團offer
    ,找工作前,看了Java核心技術 卷I 基礎知識那本書,適合我這種基礎不好的,周圍同學有看編程思想的,那個也不錯。可以參考下cyc2018和java guide兩位老哥關於java基礎常見的問題,github上直接搜索即可。
  • Java中的 "弱" 引用有啥用?
    對於簡單的情況, 手動置空是不需要程式設計師來做的, 因為在java中, 對於簡單對象, 當調用它的方法執行完畢後, 指向它的引用會被從棧中彈出, 所以它就能在下一次GC執行時被回收了。但是, 也有特殊例外.
  • 面試官:給我手寫一個哈夫曼編碼(java語言實現)
    哈弗曼樹往往都會根據哈夫曼編碼結合著來說,因此這篇文章,主要結合著面試問題來說明。一、基本概念哈夫曼樹的目的是找出存放一串字符所需的最少的二進位編碼, 原理是通過統計出每種字符出現的頻率!不斷地對其合併。
  • 適合Java新手的開源項目集合——在 GitHub 學編程
    先 clone 把源碼下載後,可以通過 java -jar FlappyBird.jar 直接運行,也可以通過運行源碼中的 GameApp:main 方法來啟動整個遊戲。每一部分都用了一張思維導圖來整理出各個知識點,既能夠對將學知識的大致了解,也方便了學習後,對已學知識的鞏固複習,可以說良心到不行。你完全可以按照自己的節奏,學習的進度去查看每一個知識點。
  • 程式設計師面試通關的 101 道真題
    我們都知道編程面試系統並不完美,許多人都在嘗試改變,但在改變之前,你必須遵循規則才能進入系統。我們就把這個問題留給經驗豐富的開發人員來解決吧,作為初級開發人員,你的重點應該是順利通過編程面試,並拿下心儀的工作。很多人都問我編程面試的問題以及如何順利通過編程面試,這就是我寫本文的初衷,希望本文能夠為程式設計師以及他們的職業生涯帶來直接或間接性的幫助。
  • Web前端和後端有什麼區別(上)
    關於Web前端與後端之間有什麼區別呢,下面有小編帶你了解一下,相信看完本文你會有新的理解。 一.定義不同 一般來說,我們把網站分為前端和後端。前端主要負責頁面展示,後端是業務邏輯的實現。
  • Java基礎教程:java反射機制教程
    很多動力節點的學員在面試中都會被問到Java反射機制這個問題,為了幫助大家更好的掌握這個知識點,小編整理了一些資料分享給大家。 一、反射概念 在正式講解反射之前,為了很好的去理解它我們先從一個案例說起。
  • Web前端和後端有什麼區別(下)
    5、最好的後臺語言是 java, php,為什麼?由於前臺界面的數據都來自後臺,如果能點後臺代碼,知道如何與後臺交互數據是最好的,這樣節省了時間,也可以讓前端代碼更加規範.否則,可能因為你的寫法和後端給來的數據不能結合,而前端代碼又要重寫,那就更麻煩了。
  • 材質、細節、尺寸、重量,一文搞懂!
    今天,小編帶你一文搞懂~行李箱買多大的呢?這個問題其實決定權不完全在我們這裡。關於拉杆箱晃動這個事情眾說紛紜,有人說這是防損壞必備的,也有人說質量太差的箱子就會晃動特別厲害,小編個人的經歷是,晃動的厲害的拉杆也可以很經用就是了,所以沒必要太在意。