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

Java弱引用集合WeakHashMap總結(jié)

 更新時(shí)間:2023年09月07日 11:20:57   作者:feiyingHiei  
這篇文章主要介紹了Java弱引用集合WeakHashMap總結(jié),WeakHashMap利用WeakReference的弱引用特性讓用戶在使用的過程中不會(huì)因?yàn)闆]有釋放Map中的資源而導(dǎo)致內(nèi)存泄露,WeakHashMap實(shí)現(xiàn)了Map接口,使用方式和其他的Map相同,需要的朋友可以參考下

前言

WeakHashMap利用WeakReference的弱引用特性讓用戶在使用的過程中不會(huì)因?yàn)闆]有釋放Map中的資源而導(dǎo)致內(nèi)存泄露。

WeakHashMap實(shí)現(xiàn)了Map接口,使用方式和其他的Map相同,需要注意的是get方法和size方法的使用。在介紹WeakHashMap之前需要先介紹一下Reference的概念。

1、Reference的實(shí)現(xiàn)

public abstract class Reference<T> {
    private T referent;   //對(duì)應(yīng)的引用對(duì)象
    volatile ReferenceQueue<? super T> queue; //引用隊(duì)列,初始化的時(shí)候從外部傳入
    Reference next;  // 當(dāng)引用對(duì)象可達(dá)性發(fā)生變化的時(shí)候,next會(huì)指向當(dāng)前引用
    transient private Reference<T> discovered;  /* used by VM */
    static private class Lock { } 
    private static Lock lock = new Lock(); //用來同步鎖操作
}

Reference類有四個(gè)直接子類,PhantomReference、FinalReference、SoftReference、WeakReference。

其中SoftReference比WeakReference約束要強(qiáng)一些,當(dāng)內(nèi)存不夠用的時(shí)候JVM才會(huì)將對(duì)應(yīng)引用的對(duì)象刪除掉,而WeakReference在對(duì)象引用不可達(dá)的時(shí)候就會(huì)被JVM清理掉,PhantomReference(虛引用)和約束更弱,get方法永遠(yuǎn)都返回null,無法像前兩者一樣可以通過get()方法獲取一個(gè)強(qiáng)引用,PhantomReference只能用來監(jiān)控對(duì)象的GC狀況。

無論哪種Reference,都有一個(gè)重要的對(duì)象來跟蹤對(duì)象的gc動(dòng)作,這個(gè)就是ReferenceQueue。

2、ReferenceQueue的實(shí)現(xiàn)

public class ReferenceQueue {
    static private class Lock { }; //鎖對(duì)象,用來同步隊(duì)列操作
    private Lock lock = new Lock(); 
    private volatile Reference<? extends T> head = null; //頭結(jié)點(diǎn)
    private long queueLength = 0; //隊(duì)列長度
}

入隊(duì)操作

boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
   synchronized (lock) {
        ReferenceQueue<?> queue = r.queue; //獲取reference之前的隊(duì)列,如果沒有綁定隊(duì)列,那就不需要入隊(duì)
        if ((queue == NULL) || (queue == ENQUEUED)) {
            return false;
        }
        assert queue == this;
        r.queue = ENQUEUED;
        r.next = (head == null) ? r : head; //把r從鏈表的頭部插入
        head = r; //頭結(jié)點(diǎn)指向r
        queueLength++; //隊(duì)列長度+1
        if (r instanceof FinalReference) {
            sun.misc.VM.addFinalRefCount(1);
        }
        lock.notifyAll(); //喚醒刪除線程刪除頭結(jié)點(diǎn)
        return true;
    }
}

出隊(duì)列的操作相似,每個(gè)reference就是鏈表中的一個(gè)節(jié)點(diǎn),next指向下一個(gè)reference節(jié)點(diǎn)。

刪除操作

public Reference<? extends T> remove(long timeout)
    throws IllegalArgumentException, InterruptedException
{
    if (timeout < 0) {
        throw new IllegalArgumentException("Negative timeout value");
    }
    synchronized (lock) {
        Reference<? extends T> r = reallyPoll(); //嘗試獲取隊(duì)列的頭結(jié)點(diǎn)
        if (r != null) return r; //獲取成功,返回
        long start = (timeout == 0) ? 0 : System.nanoTime(); //如果超時(shí)時(shí)間不為0,就記錄一下當(dāng)前的開始時(shí)間
        for (;;) {
            lock.wait(timeout);
            r = reallyPoll();
            if (r != null) return r;
            if (timeout != 0) {
                long end = System.nanoTime();
                timeout -= (end - start) / 1000_000; //計(jì)算一下等待的時(shí)間
                if (timeout <= 0) return null; //確認(rèn)等待是否是超時(shí),如果是就返回,否則就認(rèn)為是有入隊(duì)請(qǐng)求喚醒當(dāng)前線程,但是當(dāng)前線程嘗試刪除頭結(jié)點(diǎn)失敗了(被其他線程刪除了),那么繼續(xù)嘗試刪除頭結(jié)點(diǎn),再次執(zhí)行循環(huán)中的內(nèi)容直到超時(shí)
                start = end;
            }
        }
    }
}

ReferenceQueue是線程安全的,出隊(duì)入隊(duì)操作都由lock對(duì)象來保證線程安全,當(dāng)用戶線程和jvm線程同時(shí)訪問ReferenceQueue的時(shí)候不會(huì)出現(xiàn)并發(fā)問題。

WeakHashMap

WeakHashMap內(nèi)部同樣是通過一個(gè)數(shù)組來實(shí)現(xiàn)存儲(chǔ),解決沖突的方式也是使用拉鏈法,weakHashMap中重新定義了Entry類來存儲(chǔ)kv鍵值對(duì),Entry的實(shí)現(xiàn)也是實(shí)現(xiàn)WeakHashMap特性的關(guān)鍵。

1、Entry的定義

WeakHashMap重新定義了一個(gè)entry,這個(gè)entry繼承了WeakReference類并且實(shí)現(xiàn)了Entry接口,使用該Entry存儲(chǔ)鍵值對(duì)不會(huì)產(chǎn)生強(qiáng)引用

jvm在垃圾回收的時(shí)候不會(huì)認(rèn)為該引用是強(qiáng)引用,會(huì)正常的回收對(duì)象

Entry的定義如下

private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
  V value;          //存儲(chǔ)的value    
  final int hash;   //hash值
  Entry<K,V> next;  //拉鏈法解決沖突,形成單鏈表
  Entry(Object key, V value,ReferenceQueue<Object> queue, int hash, Entry<K,V> next) {
  super(key, queue);   //這里的引用對(duì)象是key,跟蹤的是key對(duì)象的垃圾回收
  this.value = value;
  this.hash  = hash;
  this.next  = next;
  }
  ...
}

Entry的構(gòu)造器需要傳入ReferenceQueue,這個(gè)queue就可以用來監(jiān)控全局的Entry被清理的情況。

2、清理操作

當(dāng)對(duì)象被垃圾回收的時(shí)候,當(dāng)前Map需要?jiǎng)h除掉對(duì)應(yīng)的Entry,因?yàn)镋ntry此時(shí)指向的對(duì)象已經(jīng)被回收,所以需要找到被JVM回收的對(duì)象對(duì)應(yīng)的Entry并且將Entry對(duì)象從Map中移除掉,實(shí)現(xiàn)方式是expungeStaleEntries方法

private void expungeStaleEntries() {
    for (Object x; (x = queue.poll()) != null; ) {
        synchronized (queue) {
            @SuppressWarnings("unchecked")
                Entry<K,V> e = (Entry<K,V>) x;
            int i = indexFor(e.hash, table.length); //從隊(duì)列中拿到entry,根據(jù)entry獲取entry鏈表在table中的索引
            Entry<K,V> prev = table[i]; //找到entry鏈表的頭結(jié)點(diǎn)
            Entry<K,V> p = prev;
            while (p != null) {
                Entry<K,V> next = p.next;
                if (p == e) {
                    if (prev == e)
                        table[i] = next; //找到對(duì)應(yīng)節(jié)點(diǎn)
                    else
                        prev.next = next;
                    e.value = null; // Help GC
                    size--;
                    break;
                }
                prev = p;
                p = next;
            }
        }
    }
}

該方法在map中的getTable()、size()和resize()方法中被調(diào)用,每次put或是get的時(shí)候都會(huì)先執(zhí)行g(shù)etTable()方法,因此每次讀寫數(shù)據(jù)的時(shí)候都會(huì)清理掉無用的entry,所以用戶不會(huì)獲取到被垃圾回收的清理entry

因此,每次用戶調(diào)用get方法或是size方法的時(shí)候,都會(huì)觸發(fā)清理操作,所以每次返回的結(jié)果可能都不相同,因?yàn)閮?nèi)部的entry持有的對(duì)象已經(jīng)被jvm回收。

線程安全問題

WeakHashMap作為容器本事不是線程安全的,但是在使用過程中,ReferenceQueue可能會(huì)被當(dāng)前業(yè)務(wù)線程和JVM線程并發(fā)訪問,ReferenceQueue是線程安全的。

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

相關(guān)文章

  • MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報(bào)錯(cuò)信息處理方案

    MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報(bào)錯(cuò)信息處理方案

    這篇文章主要介紹了MyBatis中使用#{}和${}占位符傳遞參數(shù)的各種報(bào)錯(cuò)信息處理方案,分別介紹了兩種占位符的區(qū)別,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • JavaScript Date時(shí)間對(duì)象的常用操作方法總結(jié)

    JavaScript Date時(shí)間對(duì)象的常用操作方法總結(jié)

    本文介紹了JavaScript中Date對(duì)象的常用操作方法,包括創(chuàng)建、獲取、設(shè)置本地及UTC時(shí)間等,幫助開發(fā)者靈活處理日期與時(shí)間的相關(guān)需求,需要的朋友可以參考下
    2025-10-10
  • 詳解idea maven nexus 常見命令配置

    詳解idea maven nexus 常見命令配置

    這篇文章主要介紹了idea maven nexus 常見命令配置的相關(guān)知識(shí),通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Jenkins環(huán)境搭建之下載與安裝過程

    Jenkins環(huán)境搭建之下載與安裝過程

    Jenkins是一個(gè)功能強(qiáng)大的應(yīng)用程序,允許持續(xù)集成和持續(xù)交付項(xiàng)目,集成Jenkins可以用于一些測(cè)試和部署技術(shù),對(duì)Jenkins環(huán)境搭建之下載與安裝過程感興趣的朋友跟隨小編一起看看吧
    2021-12-12
  • 關(guān)于ThreadLocal對(duì)request和response的用法說明

    關(guān)于ThreadLocal對(duì)request和response的用法說明

    這篇文章主要介紹了關(guān)于ThreadLocal對(duì)request和response的用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 簡單總結(jié)SpringMVC攔截器的使用方法

    簡單總結(jié)SpringMVC攔截器的使用方法

    今天給大家?guī)淼氖顷P(guān)于SpringMVC攔截器的相關(guān)知識(shí),文章圍繞著SpringMVC攔截器的使用方法展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 深入了解Java I/O 之File類

    深入了解Java I/O 之File類

    這篇文章主要介紹了Java I/O深入學(xué)習(xí)之File和RandomAccessFile, I/O系統(tǒng)即輸入/輸出系統(tǒng),對(duì)于一門程序語言來說,創(chuàng)建一個(gè)好的輸入/輸出系統(tǒng)并非易事。需要的朋友可以參考下
    2021-08-08
  • 詳解Java的MyBatis框架和Spring框架的整合運(yùn)用

    詳解Java的MyBatis框架和Spring框架的整合運(yùn)用

    在Web端的SSH框架整合中Spring主要負(fù)責(zé)數(shù)據(jù)庫處理,而引入MyBatis后二者的集成使用效果更佳,下面我們就來詳解Java的MyBatis框架和Spring框架的整合運(yùn)用
    2016-06-06
  • idea左側(cè)的commit框設(shè)置顯示出來方式

    idea左側(cè)的commit框設(shè)置顯示出來方式

    在IDEA中顯示左側(cè)的commit框,首先通過File-Settings-Version Control-Commit進(jìn)行設(shè)置,然后勾選Use non-modal commit interface完成
    2025-01-01
  • SpringBoot中Fat Jar的三種打包方式詳解

    SpringBoot中Fat Jar的三種打包方式詳解

    Spring Boot開發(fā)中,打包是將應(yīng)用及其所有依賴整合到一個(gè)可執(zhí)行文件中的過程,這種包含所有依賴的jar文件通常被稱為"Fat Jar",下面我們來看看SpringBoot打包Fat Jar的三種方式吧
    2025-06-06

最新評(píng)論

夏河县| 囊谦县| 舞阳县| 通渭县| 林西县| 左权县| 祁连县| 鲁甸县| 文昌市| 阜宁县| 柳林县| 汉中市| 天全县| 新丰县| 满城县| 股票| 沿河| 渝北区| 黄浦区| 屯昌县| 常州市| 吴忠市| 凤台县| 蒲城县| 武宣县| 凤城市| 思茅市| 巴彦县| 比如县| 鹰潭市| 广灵县| 龙口市| 区。| 阿尔山市| 历史| 进贤县| 凯里市| 临湘市| 贵阳市| 集贤县| 白山市|