欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺析Java中的WeakHashMap

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

WeakHashMap

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

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

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

在Java中,有四種引用類型

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

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

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

WeakHashMap如何不阻止對(duì)象回收呢 

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指向的對(duì)象
  • 因此WeakHashMap利用了WeakReference的機(jī)制來(lái)實(shí)現(xiàn)不阻止GC回收Key

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

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

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

  • 當(dāng)對(duì)象被回收的時(shí)候,進(jìn)行通知
  • WeakHashMap輪詢處理時(shí)效的Entry

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

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

為什么沒(méi)有使用看似更好的通知呢,我想是因?yàn)樵贘ava中沒(méi)有一個(gè)可靠的通知回調(diào),比如大家常說(shuō)的finalize方法,其實(shí)也不是標(biāo)準(zhǔn)的,不同的JVM可以實(shí)現(xiàn)不同,甚至是不調(diào)用這個(gè)方法。

當(dāng)然除了單純的看源碼,進(jìn)行合理的驗(yàn)證是檢驗(yàn)分析正確的一個(gè)重要方法。

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

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}")
}

我們按照如下操作

  • 點(diǎn)擊fab控件,每次對(duì)WeakhashMap對(duì)象增加一個(gè)Entry,并打印WeakHashMap的size 執(zhí)行3此
  • 在沒(méi)有強(qiáng)制觸發(fā)GC時(shí),WeakHashMap對(duì)象size一直會(huì)增加
  • 手動(dòng)出發(fā)Force GC,我們會(huì)看到MyObject有finalize方法被調(diào)用
  • 再次點(diǎn)擊fab空間,然后輸出的WeakHashMap size急劇減少。
  • 同樣我們收到在WeakHashMap增加的日志也會(huì)輸出
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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java顯式鎖詳情

    Java顯式鎖詳情

    這篇文章主要詳細(xì)的介紹了shenJava顯式鎖常用的api及標(biāo)準(zhǔn)用法,感興趣的朋友,需要的朋友可以參考下面文章里的內(nèi)容
    2021-09-09
  • 淺談圖片上傳利用request.getInputStream()獲取文件流時(shí)遇到的問(wèn)題

    淺談圖片上傳利用request.getInputStream()獲取文件流時(shí)遇到的問(wèn)題

    下面小編就為大家?guī)?lái)一篇淺談圖片上傳利用request.getInputStream()獲取文件流時(shí)遇到的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • IDEA插件EasyCode及MyBatis最優(yōu)配置步驟詳解

    IDEA插件EasyCode及MyBatis最優(yōu)配置步驟詳解

    這篇文章主要介紹了IDEA插件EasyCode MyBatis最優(yōu)配置步驟詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • SpringBoot利用ThreadPoolTaskExecutor批量插入百萬(wàn)級(jí)數(shù)據(jù)的具體實(shí)現(xiàn)

    SpringBoot利用ThreadPoolTaskExecutor批量插入百萬(wàn)級(jí)數(shù)據(jù)的具體實(shí)現(xiàn)

    ThreadPoolTaskExecutor是Spring提供的任務(wù)執(zhí)行器實(shí)現(xiàn)之一,允許開發(fā)者配置線程池參數(shù)以適應(yīng)不同的應(yīng)用場(chǎng)景,創(chuàng)建 ThreadPoolTaskExecutor 實(shí)例并設(shè)置核心和最大線程數(shù)等屬性可以優(yōu)化性能,本文介紹了SpringBoot利用ThreadPoolTaskExecutor批量插入百萬(wàn)級(jí)數(shù)據(jù)的具體實(shí)現(xiàn)
    2024-12-12
  • mybatis-plus開啟sql打印的三種方式總結(jié)

    mybatis-plus開啟sql打印的三種方式總結(jié)

    這篇文章主要給大家介紹了mybatisplus開啟sql打印的三種方式,文章通過(guò)代碼示例介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下
    2023-11-11
  • Spring時(shí)間戳(日期)格式轉(zhuǎn)換方式

    Spring時(shí)間戳(日期)格式轉(zhuǎn)換方式

    這篇文章主要介紹了Spring時(shí)間戳(日期)格式轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 如何在 Java 中利用 redis 實(shí)現(xiàn) LBS 服務(wù)

    如何在 Java 中利用 redis 實(shí)現(xiàn) LBS 服務(wù)

    基于位置的服務(wù),是指通過(guò)電信移動(dòng)運(yùn)營(yíng)商的無(wú)線電通訊網(wǎng)絡(luò)或外部定位方式,獲取移動(dòng)終端用戶的位置信息,在GIS平臺(tái)的支持下,為用戶提供相應(yīng)服務(wù)的一種增值業(yè)務(wù)。下面我們來(lái)一起學(xué)習(xí)一下吧
    2019-06-06
  • Spring?IOC容器FactoryBean工廠Bean實(shí)例

    Spring?IOC容器FactoryBean工廠Bean實(shí)例

    這篇文章主要為大家介紹了Spring?IOC容器FactoryBean工廠Bean實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Springboot整合log4j2日志全解總結(jié)

    Springboot整合log4j2日志全解總結(jié)

    這篇文章主要介紹了Springboot整合log4j2日志全解總結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-12-12
  • Spring排序機(jī)制之接口與注解的使用方法

    Spring排序機(jī)制之接口與注解的使用方法

    本文介紹了Spring中多種排序機(jī)制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了詳細(xì)示例,并指導(dǎo)如何選擇合適的排序機(jī)制來(lái)控制Bean的加載順序和優(yōu)先級(jí),感興趣的朋友一起看看吧
    2025-02-02

最新評(píng)論