最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺析Java中的WeakHashMap

 更新時間:2023年09月08日 08:35:44   作者:洞之蟬  
這篇文章主要介紹了淺析Java中的WeakHashMap,WeakHashMap其實和HashMap大多數(shù)行為是一樣的,只是WeakHashMap不會阻止GC回收key對象,那么WeakHashMap是怎么做到的呢,這就是我們研究的主要問題,需要的朋友可以參考下

WeakHashMap

在Java或者是Android編程中,我們一般都會使用到Map,比如HashMap這樣的具體實現(xiàn)。更高級一點,我們可能會使用WeakHashMap。

WeakHashMap其實和HashMap大多數(shù)行為是一樣的,只是WeakHashMap不會阻止GC回收key對象(不是value),那么WeakHashMap是怎么做到的呢,這就是我們研究的主要問題。

在開始WeakHashMap之前,我們先要對弱引用有一定的了解。

在Java中,有四種引用類型

  • 強引用(Strong Reference),我們正常編碼時默認的引用類型,強應(yīng)用之所以為強,是因為如果一個對象到GC Roots強引用可到達,就可以阻止GC回收該對象
  • 軟引用(Soft Reference)阻止GC回收的能力相對弱一些,如果是軟引用可以到達,那么這個對象會停留在內(nèi)存更時間上長一些。當內(nèi)存不足時垃圾回收器才會回收這些軟引用可到達的對象
  • 弱引用(WeakReference)無法阻止GC回收,如果一個對象時弱引用可到達,那么在下一個GC回收執(zhí)行時,該對象就會被回收掉。
  • 虛引用(Phantom Reference)十分脆弱,它的唯一作用就是當其指向的對象被回收之后,自己被加入到引用隊列,用作記錄該引用指向的對象已被銷毀

這其中還有一個概念叫做引用隊列(Reference Queue)

  • 一般情況下,一個對象標記為垃圾(并不代表回收了)后,會加入到引用隊列。
  • 對于虛引用來說,它指向的對象會只有被回收后才會加入引用隊列,所以可以用作記錄該引用指向的對象是否回收。

WeakHashMap如何不阻止對象回收呢 

private static final class Entry<K, V> extends WeakReference<K> implements
Map.Entry<K, V> {
int hash;
boolean isNull;
V value;
Entry<K, V> next;
interface Type<R, K, V> {
R get(Map.Entry<K, V> entry);
}
Entry(K key, V object, ReferenceQueue<K> queue) {
super(key, queue);
isNull = key == null;
hash = isNull ? 0 : key.hashCode();
value = object;
}

如源碼所示,

  • WeakHashMap的Entry繼承了WeakReference。
  • 其中Key作為了WeakReference指向的對象
  • 因此WeakHashMap利用了WeakReference的機制來實現(xiàn)不阻止GC回收Key

如何刪除被回收的key數(shù)據(jù)呢

在Javadoc中關(guān)于WeakHashMap有這樣的描述,當key不再引用時,其對應(yīng)的key/value也會被移除。

那么是如何移除的呢,這里我們通常有兩種假設(shè)策略

  • 當對象被回收的時候,進行通知
  • WeakHashMap輪詢處理時效的Entry

而WeakHashMap采用的是輪詢的形式,在其put/get/size等方法調(diào)用的時候都會預(yù)先調(diào)用一個poll的方法,來檢查并刪除失效的Entry

void poll() {
Entry<K, V> toRemove;
while ((toRemove = (Entry<K, V>) referenceQueue.poll()) != null) {
removeEntry(toRemove);
Log.d(LOGTAG, "removeEntry=" + toRemove.value);
}
}

為什么沒有使用看似更好的通知呢,我想是因為在Java中沒有一個可靠的通知回調(diào),比如大家常說的finalize方法,其實也不是標準的,不同的JVM可以實現(xiàn)不同,甚至是不調(diào)用這個方法。

當然除了單純的看源碼,進行合理的驗證是檢驗分析正確的一個重要方法。

這里首先,我們定義一個MyObject類,處理一下finalize方法(在我的測試機上可以正常調(diào)用,僅僅做為輔助驗證手段)

class MyObject(val id: String) : Any() {
protected fun finalize() {
Log.i("MainActivity", "Object($id) finalize method is called")
}
}

然后是調(diào)用者的代碼,如下

private val weakHashMap = WeakHashMap<Any, Int>()
var count : Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)
dumpWeakInfo()
fab.setOnClickListener { view ->
//System.gc()// this seldom works use Android studio force gc stop
weakHashMap.put(MyObject(count.toString()), count)
count ++
dumpWeakInfo()
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
fun dumpWeakInfo() {
Log.i("MainActivity", "dumpWeakInfo weakInfo.size=${weakHashMap.size}")
}

我們按照如下操作

  • 點擊fab控件,每次對WeakhashMap對象增加一個Entry,并打印WeakHashMap的size 執(zhí)行3此
  • 在沒有強制觸發(fā)GC時,WeakHashMap對象size一直會增加
  • 手動出發(fā)Force GC,我們會看到MyObject有finalize方法被調(diào)用
  • 再次點擊fab空間,然后輸出的WeakHashMap size急劇減少。
  • 同樣我們收到在WeakHashMap增加的日志也會輸出
I/MainActivity(10202): dumpWeakInfo weakInfo.size=1
I/MainActivity(10202): dumpWeakInfo weakInfo.size=2
I/MainActivity(10202): dumpWeakInfo weakInfo.size=3
I/MainActivity(10202): Object(2) finalize method is called
I/MainActivity(10202): Object(1) finalize method is called
I/MainActivity(10202): Object(0) finalize method is called
I/WeakHashMap(10202): removeEntry=2
I/WeakHashMap(10202): removeEntry=0
I/WeakHashMap(10202): removeEntry=1
I/MainActivity(10202): dumpWeakInfo weakInfo.size=1

注意:System.gc()并不一定可以工作,建議使用Android Studio的Force GC

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

相關(guān)文章

  • 詳解Java Stream實現(xiàn)精準數(shù)據(jù)分組與比例計算技巧

    詳解Java Stream實現(xiàn)精準數(shù)據(jù)分組與比例計算技巧

    這篇文章主要介紹了Java Stream實現(xiàn)精準數(shù)據(jù)分組與比例計算技巧,通過具體的實戰(zhàn)案例進行詳細講解,首先我們會介紹如何使用Stream對數(shù)據(jù)進行分組,然后通過收集器對分組后的數(shù)據(jù)進行統(tǒng)計,最后計算出每種類型的占比,需要的朋友可以參考下
    2026-01-01
  • 深入解析Java的Spring框架中bean的依賴注入

    深入解析Java的Spring框架中bean的依賴注入

    這篇文章主要介紹了Java的Spring框架中bean的依賴注入,講解了以構(gòu)造函數(shù)為基礎(chǔ)的依賴注入和基于setter方法的依賴注入的方式,需要的朋友可以參考下
    2015-12-12
  • Spring Boot 配置加載全解析從 @ComponentScan 到自動配置原理解析

    Spring Boot 配置加載全解析從 @ComponentScan 到自動配

    本文給大家介紹了Spring Boot 配置加載全解析從@ComponentScan到自動配置原理,通過實戰(zhàn)案例展示了如何基于@Conditional實現(xiàn)JDK版本條件裝配,并了詳細步驟和配置原理,感興趣的朋友一起看看吧
    2026-05-05
  • Java中的運算符有哪些詳解

    Java中的運算符有哪些詳解

    這篇文章主要給大家介紹了關(guān)于Java中運算符有哪些的相關(guān)資料,包括算術(shù)運算符、關(guān)系運算符、邏輯運算符、位運算符、增量運算符和自增/自減運算符,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • SpringBoot實現(xiàn)定時任務(wù)的三種方式小結(jié)

    SpringBoot實現(xiàn)定時任務(wù)的三種方式小結(jié)

    這篇文章主要介紹了SpringBoot實現(xiàn)定時任務(wù)的三種方式小結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java詳細講解不同版本的接口語法和抽象類與接口的區(qū)別

    Java詳細講解不同版本的接口語法和抽象類與接口的區(qū)別

    對于面向?qū)ο缶幊虂碚f,抽象是它的一大特征之一,在?Java?中可以通過兩種形式來體現(xiàn)OOP的抽象:接口和抽象類,下面這篇文章主要給大家介紹了關(guān)于Java入門基礎(chǔ)之抽象類與接口的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • java開發(fā)線上事故理解RocketMQ異步精髓

    java開發(fā)線上事故理解RocketMQ異步精髓

    這篇文章主要介紹了java開發(fā)線上事故理解RocketMQ異步精髓
    2022-07-07
  • 教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    Mybatis自身通過了逆向工程來幫助我們快速生成代碼,但Mybatis-plus卻更加強大,不僅僅可以生成dao,pojo,mapper,還有基本的controller和service層代碼,接下來我們來寫一個簡單的人門案例是看看如何mybatis-plus是怎么實現(xiàn)的,需要的朋友可以參考下
    2021-06-06
  • java解析xml文本的示例方法

    java解析xml文本的示例方法

    這篇文章主要為大家詳細介紹了java解析xml文本的相關(guān)方法,文中的示例代碼講解詳細,具有一定的借鑒價值,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-12-12
  • SpringBoot整合Jackson超詳細用法(附Jackson工具類)

    SpringBoot整合Jackson超詳細用法(附Jackson工具類)

    這篇文章主要介紹了SpringBoot整合Jackson超詳細教程,本篇講的是Jackson的詳細用法,Jackson工具類在文章最后,直接復(fù)制粘貼即可使用,需要的朋友可以參考下
    2023-03-03

最新評論

阿勒泰市| 当雄县| 铅山县| 石屏县| 蓬莱市| 兴安盟| 平舆县| 德阳市| 巢湖市| 六枝特区| 阜阳市| 奇台县| 山阴县| 汾西县| 牟定县| 康平县| 澎湖县| 武穴市| 阜城县| 邓州市| 苗栗县| 湖北省| 渑池县| 天津市| 灵山县| 博客| 丰宁| 竹山县| 曲水县| 汕尾市| 鲁甸县| 府谷县| 嘉峪关市| 墨江| 周至县| 蓬溪县| 顺平县| 资兴市| 屯门区| 庄河市| 比如县|