亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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ì)列長(zhǎng)度
}

入隊(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ì)列長(zhǎng)度+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)文章

  • SpringCache之 @CachePut的使用

    SpringCache之 @CachePut的使用

    這篇文章主要介紹了SpringCache之 @CachePut的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • spring boot如何加入mail郵件支持

    spring boot如何加入mail郵件支持

    這篇文章主要介紹了spring boot如何加入mail郵件支持,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • IDEA找不到j(luò)dk該如何解決

    IDEA找不到j(luò)dk該如何解決

    這篇文章主要給大家介紹了關(guān)于IDEA找不到j(luò)dk該如何解決的相關(guān)資料,剛安裝好IDEA后,我們運(yùn)行一個(gè)項(xiàng)目時(shí)候,有時(shí)候會(huì)遇到顯示找不到Java的JDK,需要的朋友可以參考下
    2023-11-11
  • spring @Scheduled注解的使用誤區(qū)及解決

    spring @Scheduled注解的使用誤區(qū)及解決

    這篇文章主要介紹了spring @Scheduled注解的使用誤區(qū)及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java網(wǎng)絡(luò)編程基礎(chǔ)教程之Socket入門實(shí)例

    Java網(wǎng)絡(luò)編程基礎(chǔ)教程之Socket入門實(shí)例

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程基礎(chǔ)教程之Socket入門實(shí)例,本文講解了創(chuàng)建Socket、Socket發(fā)送數(shù)據(jù)、Socket讀取數(shù)據(jù)、關(guān)閉Socket等內(nèi)容,都是最基礎(chǔ)的知識(shí)點(diǎn),需要的朋友可以參考下
    2014-09-09
  • IDEA中設(shè)置Run Dashboard方式

    IDEA中設(shè)置Run Dashboard方式

    這篇文章主要介紹了IDEA中設(shè)置Run Dashboard方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 基于Mock測(cè)試Spring MVC接口過程解析

    基于Mock測(cè)試Spring MVC接口過程解析

    這篇文章主要介紹了基于Mock測(cè)試Spring MVC接口過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Java請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向區(qū)別詳解

    Java請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向區(qū)別詳解

    這篇文章主要介紹了Java請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向區(qū)別詳解,請(qǐng)求轉(zhuǎn)發(fā)和請(qǐng)求重定向,但二者是完全不同的,所以我們今天就來盤他們的區(qū)別介紹,需要的朋友可以參考一下
    2022-07-07
  • Java關(guān)于后端怎么去接收Date、LocalDateTime類型的參數(shù)詳解

    Java關(guān)于后端怎么去接收Date、LocalDateTime類型的參數(shù)詳解

    這篇文章主要介紹了java關(guān)于后端怎么去接收Date、LocalDateTime類型的參數(shù),文中有詳細(xì)的代碼流程,對(duì)我們學(xué)習(xí)或工作有一定的參考價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Mybatis-Plus?新增獲取自增列id方式

    Mybatis-Plus?新增獲取自增列id方式

    這篇文章主要介紹了Mybatis-Plus?新增獲取自增列id方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評(píng)論