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

Java中的WeakHashMap詳解

 更新時(shí)間:2023年09月06日 09:37:02   作者:jieniyimiao  
這篇文章主要介紹了Java中的WeakHashMap詳解,WeakHashMap可能平時(shí)使用的頻率并不高,但是你可能聽(tīng)過(guò)WeakHashMap會(huì)進(jìn)行自動(dòng)回收吧,下面就對(duì)其原理進(jìn)行分析,需要的朋友可以參考下

楔子

WeakHashMap ,此種Map的特點(diǎn)是,當(dāng)除了自身有對(duì)key的引用外,此key沒(méi)有其他引用那么此map會(huì)自動(dòng)丟棄此值,所以比較適合做緩存。

WeakHashMap 的這種特性比較適合實(shí)現(xiàn)類(lèi)似本地、堆內(nèi)緩存的存儲(chǔ)機(jī)制——緩存的失效依賴(lài)于GC收集器的行為

WeakHashMap 的定義如下:

public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>

簡(jiǎn)單來(lái)說(shuō), WeakHashMap 實(shí)現(xiàn)了Map接口,基于 hash-table 實(shí)現(xiàn),在這種Map中,key的類(lèi)型是 WeakReference 。如果對(duì)應(yīng)的key被回收,則這個(gè)key指向的對(duì)象會(huì)被從Map容器中移除。

WeakHashMap 跟普通的HashMap不同,WeakHashMap的行為一定程度上基于垃圾收集器的行為,因此一些Map數(shù)據(jù)結(jié)構(gòu)對(duì)應(yīng)的常識(shí)在WeakHashMap上會(huì)失效——size()方法的返回值會(huì)隨著程序的運(yùn)行變小,isEmpty()方法的返回值會(huì)從false變成true等等。

實(shí)例

此例子中聲明了兩個(gè)Map對(duì)象,一個(gè)是HashMap,一個(gè)是WeakHashMap,同時(shí)向兩個(gè)map中放入a、b兩個(gè)對(duì)象,當(dāng)HashMap remove掉a 并且將a、b都指向null時(shí),WeakHashMap中的a將自動(dòng)被回收掉。

出現(xiàn)這個(gè)狀況的原因是,對(duì)于a對(duì)象而言,當(dāng)HashMap remove掉并且將a指向null后,除了WeakHashMap中還保存a外已經(jīng)沒(méi)有指向a的指針了,所以WeakHashMap會(huì)自動(dòng)舍棄掉a,而對(duì)于b對(duì)象雖然指向了null,但HashMap中還有指向b的指針。

弱引用( WeakReference )的特性是:當(dāng)gc線(xiàn)程發(fā)現(xiàn)某個(gè)對(duì)象只有弱引用指向它,那么就會(huì)將其銷(xiāo)毀并回收內(nèi)存。

WeakHashMap<UniqueImageName, BigImage> map = new WeakHashMap<>();
BigImage bigImage = new BigImage("image_id");
UniqueImageName imageName = new UniqueImageName("name_of_big_image"); //強(qiáng)引用
map.put(imageName, bigImage);
assertTrue(map.containsKey(imageName));
imageName = null; //map中的values對(duì)象成為弱引用對(duì)象
System.gc(); //主動(dòng)觸發(fā)一次GC
await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);

在這里插入圖片描述

典型使用場(chǎng)景: tomcat兩級(jí)緩存

tomcat的源碼里,實(shí)現(xiàn)緩存時(shí)會(huì)用到WeakHashMap

package org.apache.tomcat.util.collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
public final class ConcurrentCache<K,V> {
    private final int size;
    private final Map<K,V> eden;
    private final Map<K,V> longterm;
    public ConcurrentCache(int size) {
        this.size = size;
        this.eden = new ConcurrentHashMap<>(size);
        this.longterm = new WeakHashMap<>(size);
    }
    public V get(K k) {
        V v = this.eden.get(k);
        if (v == null) {
            synchronized (longterm) {
                v = this.longterm.get(k);
            }
            if (v != null) {
                this.eden.put(k, v);
            }
        }
        return v;
    }
    public void put(K k, V v) {
        if (this.eden.size() >= size) {
            synchronized (longterm) {
                this.longterm.putAll(this.eden);
            }
            this.eden.clear();
        }
        this.eden.put(k, v);
    }
}

源碼中有 eden 和 longterm 的兩個(gè)map,對(duì)jvm堆區(qū)有所了解的話(huà),可以猜測(cè)出tomcat在這里是使用 ConcurrentHashMap 和 WeakHashMap 做了 分代的緩存 。

  • 在put方法里,在插入一個(gè)k-v時(shí),先檢查eden緩存的容量是不是超了。沒(méi)有超就直接放入eden緩存,如果超了則鎖定longterm將eden中所有的k-v都放入longterm。再將eden清空并插入k-v。
  • 在get方法中,也是優(yōu)先從eden中找對(duì)應(yīng)的v,如果沒(méi)有則進(jìn)入longterm緩存中查找,找到后就加入eden緩存并返回。

經(jīng)過(guò)這樣的設(shè)計(jì),相對(duì)常用的對(duì)象都能在eden緩存中找到,不常用(有可能被銷(xiāo)毀的對(duì)象)的則進(jìn)入longterm緩存。而longterm的key的實(shí)際對(duì)象沒(méi)有其他引用指向它時(shí),gc就會(huì)自動(dòng)回收heap中該弱引用指向的實(shí)際對(duì)象,弱引用進(jìn)入引用隊(duì)列。longterm調(diào)用expungeStaleEntries()方法,遍歷引用隊(duì)列中的弱引用,并清除對(duì)應(yīng)的Entry,不會(huì)造成內(nèi)存空間的浪費(fèi)。

利用WeakHashMap實(shí)現(xiàn)內(nèi)存緩存

可以看出,WeakHashMap的這種特性比較適合實(shí)現(xiàn)類(lèi)似本地、堆內(nèi)緩存的存儲(chǔ)機(jī)制——緩存的失效依賴(lài)于GC收集器的行為。假設(shè)一種應(yīng)用場(chǎng)景:我們需要保存一批大的圖片對(duì)象,其中values是圖片的內(nèi)容,key是圖片的名字,這里我們需要選擇一種合適的容器保存這些對(duì)象。

使用普通的HashMap并不是好的選擇,這些大對(duì)象將會(huì)占用很多內(nèi)存,并且還不會(huì)被GC回收,除非我們?cè)趯?duì)應(yīng)的key廢棄之前主動(dòng)remove掉這些元素。WeakHashMap非常適合使用在這種場(chǎng)景下,下面的代碼演示了具體的實(shí)現(xiàn):

WeakHashMap<UniqueImageName, BigImage> map = new WeakHashMap<>();
BigImage bigImage = new BigImage("image_id");
UniqueImageName imageName = new UniqueImageName("name_of_big_image"); //強(qiáng)引用
map.put(imageName, bigImage);
assertTrue(map.containsKey(imageName));
imageName = null; //map中的values對(duì)象成為弱引用對(duì)象
System.gc(); //主動(dòng)觸發(fā)一次GC
await().atMost(10, TimeUnit.SECONDS).until(map::isEmpty);

首先,創(chuàng)建一個(gè)WeakHashMap對(duì)象來(lái)存儲(chǔ)BigImage實(shí)例,對(duì)應(yīng)的key是UniqueImageName對(duì)象,保存到WeakHashMap里的時(shí)候,key是一個(gè)弱引用類(lèi)型。

然后,我們將imageName設(shè)置為null,這樣就沒(méi)有其他強(qiáng)引用指向bigImage對(duì)象,按照WeakHashMap的規(guī)則,在下一次GC周期中會(huì)回收bigImage對(duì)象。

通過(guò)System.gc()主動(dòng)觸發(fā)一次GC過(guò)程,然后可以發(fā)現(xiàn)WeakHashMap成為空的了。

強(qiáng)引用、軟引用和弱引用

  • 強(qiáng)引用( Strong Reference )
  • 軟引用( Soft Reference )
  • 弱引用 ( WeakReference )

強(qiáng)引用

被強(qiáng)引用指向的對(duì)象,絕對(duì)不會(huì)被垃圾收集器回收。

Integer prime = 1;

這個(gè)語(yǔ)句中prime對(duì)象就有一個(gè)強(qiáng)引用。

軟引用

被 SoftReference 指向的對(duì)象可能會(huì)被垃圾收集器回收,但是只有在JVM內(nèi)存不夠的情況下才會(huì)回收;如下代碼可以創(chuàng)建一個(gè)軟引用:

Integer prime = 1;  
	SoftReference<Integer> soft = new SoftReference<Integer>(prime);
	prime = null;

弱引用

當(dāng)一個(gè)對(duì)象僅僅被 WeakReference 引用時(shí),在下個(gè)垃圾收集周期時(shí)候該對(duì)象就會(huì)被回收。我們通過(guò)下面代碼創(chuàng)建一個(gè)WeakReference:

Integer prime = 1;  
	WeakReference<Integer> soft = new WeakReference<Integer>(prime);
	prime = null;

當(dāng)把prime賦值為null的時(shí)候,原prime對(duì)象會(huì)在下一個(gè)垃圾收集周期中被回收,因?yàn)橐呀?jīng)沒(méi)有強(qiáng)引用指向它。

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

相關(guān)文章

  • 詳解SpringMVC Controller介紹及常用注解

    詳解SpringMVC Controller介紹及常用注解

    本篇文章主要介紹了SpringMVC Controller介紹及常用注解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • spring framework體系結(jié)構(gòu)及模塊jar依賴(lài)關(guān)系詳解

    spring framework體系結(jié)構(gòu)及模塊jar依賴(lài)關(guān)系詳解

    在本篇文章里小編給大家整理的是關(guān)于spring framework體系結(jié)構(gòu)及模塊jar依賴(lài)關(guān)系,對(duì)此有興趣的朋友們可以學(xué)習(xí)下。
    2019-09-09
  • Java實(shí)現(xiàn)的猴子吃桃問(wèn)題算法示例

    Java實(shí)現(xiàn)的猴子吃桃問(wèn)題算法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)的猴子吃桃問(wèn)題算法,簡(jiǎn)單描述了猴子吃桃問(wèn)題并結(jié)合實(shí)例形式給出了java解決猴子吃桃問(wèn)題的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-10-10
  • Spring?Boot?中使用@KafkaListener并發(fā)批量接收消息的完整代碼

    Spring?Boot?中使用@KafkaListener并發(fā)批量接收消息的完整代碼

    kakfa是我們?cè)陧?xiàng)目開(kāi)發(fā)中經(jīng)常使用的消息中間件。由于它的寫(xiě)性能非常高,因此,經(jīng)常會(huì)碰到讀取Kafka消息隊(duì)列時(shí)擁堵的情況,這篇文章主要介紹了Spring?Boot?中使用@KafkaListener并發(fā)批量接收消息,需要的朋友可以參考下
    2023-02-02
  • Java并發(fā)編程之工具類(lèi)Semaphore的使用

    Java并發(fā)編程之工具類(lèi)Semaphore的使用

    目前幾乎所有的語(yǔ)言都支持信號(hào)量機(jī)制,Java也不例外.Java中提供了Semaphore并發(fā)工具類(lèi)來(lái)支持信號(hào)量機(jī)制,下面我們就來(lái)了解Java實(shí)現(xiàn)的信號(hào)量機(jī)制,文中有非常詳細(xì)的介紹,需要的朋友可以參考下
    2021-06-06
  • IDEA?中使用?Hudi的示例代碼

    IDEA?中使用?Hudi的示例代碼

    這篇文章主要介紹了IDEA?中使用?Hudi的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • Java字符串格式化功能?String.format用法詳解

    Java字符串格式化功能?String.format用法詳解

    String類(lèi)的format()方法用于創(chuàng)建格式化的字符串以及連接多個(gè)字符串對(duì)象,熟悉C語(yǔ)言的同學(xué)應(yīng)該記得C語(yǔ)言的sprintf()方法,兩者有類(lèi)似之處,format()方法有兩種重載形式
    2024-09-09
  • 解決java調(diào)用python代碼返回值中文亂碼問(wèn)題

    解決java調(diào)用python代碼返回值中文亂碼問(wèn)題

    這篇文章主要介紹了解決java調(diào)用python代碼返回值中文亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 淺談自定義注解在Spring中的應(yīng)用

    淺談自定義注解在Spring中的應(yīng)用

    這篇文章主要介紹了淺談自定義注解在Spring中的應(yīng)用,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • SpringBoot如何訪(fǎng)問(wèn)不同的數(shù)據(jù)庫(kù)的方法實(shí)現(xiàn)

    SpringBoot如何訪(fǎng)問(wèn)不同的數(shù)據(jù)庫(kù)的方法實(shí)現(xiàn)

    本文主要介紹了在SpringBoot應(yīng)用中配置和管理多個(gè)數(shù)據(jù)源的方法,包括使用SpringBoot官方支持的配置方式和第三方庫(kù)實(shí)現(xiàn)多數(shù)據(jù)源配置,感興趣的可以了解一下
    2024-11-11

最新評(píng)論

金寨县| 防城港市| 宁海县| 海原县| 拜泉县| 营山县| 家居| 黄山市| 尉氏县| 盐津县| 德格县| 土默特右旗| 安化县| 汾阳市| 桂林市| 靖西县| 长沙市| 稷山县| 新津县| 宝兴县| 亚东县| 舒兰市| 庆城县| 安徽省| 县级市| 耿马| 吉水县| 富源县| 枣阳市| 兴义市| 湘阴县| 睢宁县| 佛山市| 绥滨县| 桃园县| 景宁| 如皋市| 廊坊市| 抚顺市| 潼关县| 西安市|