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

Java中的四種引用類型之強(qiáng)引用、軟引用、弱引用和虛引用及用法詳解

 更新時(shí)間:2025年08月18日 11:32:15   作者:北辰alk  
Java的四種引用類型(強(qiáng)、軟、弱、虛)控制對(duì)象生命周期,分別在不同內(nèi)存壓力下回收,適用于緩存、資源清理等場(chǎng)景,配合ReferenceQueue實(shí)現(xiàn)高效內(nèi)存管理,本文將全面剖析這四種引用類型的概念、用法、實(shí)現(xiàn)原理以及實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友一起看看吧

Java提供了四種不同強(qiáng)度的引用類型,它們直接影響對(duì)象的生命周期和垃圾收集行為。理解這些引用類型的區(qū)別對(duì)于編寫高效、內(nèi)存友好的Java程序至關(guān)重要。本文將全面剖析這四種引用類型的概念、用法、實(shí)現(xiàn)原理以及實(shí)際應(yīng)用場(chǎng)景。

一、引用類型概述

Java中的引用類型決定了對(duì)象與垃圾收集器(GC)的互動(dòng)方式:

引用類型GC行為用途場(chǎng)景
強(qiáng)引用默認(rèn)永不回收普通對(duì)象引用
軟引用SoftReference內(nèi)存不足時(shí)回收內(nèi)存敏感緩存
弱引用WeakReference下次GC時(shí)回收規(guī)范化映射、臨時(shí)緩存
虛引用PhantomReference隨時(shí)可能回收對(duì)象回收跟蹤、清理操作

二、強(qiáng)引用(Strong Reference)

2.1 基本概念

強(qiáng)引用是Java程序中最常見的引用類型,也是默認(rèn)的引用方式。只要強(qiáng)引用存在,對(duì)象就永遠(yuǎn)不會(huì)被垃圾收集器回收。

Object obj = new Object(); // 強(qiáng)引用

2.2 特點(diǎn)

  • 生命周期:只要引用鏈可達(dá),對(duì)象就始終存活
  • 回收條件:顯式置為null或超出作用域
  • 內(nèi)存泄漏:不當(dāng)使用會(huì)導(dǎo)致內(nèi)存泄漏

2.3 示例分析

public class StrongReferenceDemo {
    public static void main(String[] args) {
        Object strongRef = new Object(); // 強(qiáng)引用
        // 取消強(qiáng)引用
        strongRef = null;
        // 此時(shí)對(duì)象可以被GC回收
        System.gc();
    }
}

2.4 內(nèi)存泄漏場(chǎng)景

public class MemoryLeakDemo {
    private static List<Object> list = new ArrayList<>();
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Object obj = new Object();
            list.add(obj); // 靜態(tài)集合持有強(qiáng)引用
            obj = null; // 無(wú)效操作,因?yàn)閘ist仍持有引用
        }
        // 即使obj=null,對(duì)象仍然無(wú)法被回收
    }
}

三、軟引用(SoftReference)

3.1 基本概念

軟引用描述一些還有用但非必需的對(duì)象。只有在內(nèi)存不足時(shí)(OOM前),GC才會(huì)回收這些對(duì)象。

SoftReference<Object> softRef = new SoftReference<>(new Object());

3.2 特點(diǎn)

  • 內(nèi)存敏感:在內(nèi)存充足時(shí)表現(xiàn)如強(qiáng)引用
  • 回收策略:內(nèi)存不足時(shí)根據(jù)LRU算法回收
  • 使用場(chǎng)景:適合實(shí)現(xiàn)內(nèi)存敏感緩存

3.3 實(shí)現(xiàn)原理

public class SoftReference<T> extends Reference<T> {
    // 由JVM維護(hù)的時(shí)間戳,記錄最后訪問時(shí)間
    private long timestamp;
    public SoftReference(T referent) {
        super(referent);
        this.timestamp = clock;
    }
    // JVM在GC時(shí)會(huì)調(diào)用此方法
    void updateTimestamp() {
        this.timestamp = clock;
    }
}

3.4 緩存示例

public class ImageCache {
    private final Map<String, SoftReference<BufferedImage>> cache = new HashMap<>();
    public BufferedImage getImage(String path) {
        BufferedImage image = null;
        // 檢查緩存
        SoftReference<BufferedImage> ref = cache.get(path);
        if (ref != null) {
            image = ref.get();
        }
        // 緩存未命中
        if (image == null) {
            image = loadImageFromDisk(path);
            cache.put(path, new SoftReference<>(image));
        }
        return image;
    }
    private BufferedImage loadImageFromDisk(String path) {
        // 實(shí)際實(shí)現(xiàn)從磁盤加載圖像
        return null;
    }
}

3.5 回收測(cè)試

public class SoftReferenceDemo {
    public static void main(String[] args) {
        SoftReference<byte[]> softRef = new SoftReference<>(new byte[1024 * 1024 * 10]); // 10MB
        System.out.println("GC前: " + softRef.get());
        System.gc();
        System.out.println("GC后(內(nèi)存充足): " + softRef.get());
        try {
            byte[] bigArray = new byte[1024 * 1024 * 100]; // 強(qiáng)制OOM
        } catch (OutOfMemoryError e) {
            System.out.println("OOM后: " + softRef.get()); // 可能為null
        }
    }
}

四、弱引用(WeakReference)

4.1 基本概念

弱引用描述非必需對(duì)象,無(wú)論內(nèi)存是否充足,只要發(fā)生GC就會(huì)被回收。

WeakReference<Object> weakRef = new WeakReference<>(new Object());

4.2 特點(diǎn)

  • 生命周期短:只能存活到下一次GC
  • 自動(dòng)回收:無(wú)需手動(dòng)清除
  • 使用場(chǎng)景:規(guī)范化映射、臨時(shí)緩存

4.3 WeakHashMap實(shí)現(xiàn)

public class WeakHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V> {
    // 使用弱引用作為Entry的key
    private static class Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V> {
        V value;
        int hash;
        Entry<K,V> next;
        Entry(K key, V value, ReferenceQueue<K> queue, int hash, Entry<K,V> next) {
            super(key, queue); // key被弱引用持有
            this.value = value;
            this.hash = hash;
            this.next = next;
        }
    }
}

4.4 緩存示例

public class WeakCache<K,V> {
    private final Map<K, WeakReference<V>> cache = new HashMap<>();
    public void put(K key, V value) {
        cache.put(key, new WeakReference<>(value));
    }
    public V get(K key) {
        WeakReference<V> ref = cache.get(key);
        return ref != null ? ref.get() : null;
    }
    // 定期清理null值的WeakReference
    public void cleanUp() {
        cache.entrySet().removeIf(entry -> 
            entry.getValue() == null || entry.getValue().get() == null);
    }
}

4.5 回收測(cè)試

public class WeakReferenceDemo {
    public static void main(String[] args) {
        WeakReference<Object> weakRef = new WeakReference<>(new Object());
        System.out.println("GC前: " + weakRef.get());
        System.gc();
        // 注意:這里不能保證GC立即執(zhí)行,可能需要多次調(diào)用或增加內(nèi)存壓力
        System.out.println("GC后: " + weakRef.get()); // 很可能為null
    }
}

五、虛引用(PhantomReference)

5.1 基本概念

虛引用是最弱的引用類型,無(wú)法通過它獲取對(duì)象實(shí)例,主要用于跟蹤對(duì)象被回收的狀態(tài)。

ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);

5.2 特點(diǎn)

  • 不可達(dá)性:get()始終返回null
  • 回收通知:通過ReferenceQueue獲得回收通知
  • 使用場(chǎng)景:精細(xì)化的對(duì)象回收后處理

5.3 實(shí)現(xiàn)原理

public class PhantomReference<T> extends Reference<T> {
    public T get() {
        return null; // 始終返回null
    }
    public PhantomReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }
}

5.4 資源清理示例

public class ResourceCleaner {
    private static final ReferenceQueue<Object> queue = new ReferenceQueue<>();
    private static final List<CleanupReference> references = new ArrayList<>();
    public static void register(Object resource, Runnable cleanupAction) {
        references.add(new CleanupReference(resource, cleanupAction, queue));
    }
    public static void cleanup() {
        CleanupReference ref;
        while ((ref = (CleanupReference) queue.poll()) != null) {
            ref.cleanup();
            references.remove(ref);
        }
    }
    private static class CleanupReference extends PhantomReference<Object> {
        private final Runnable cleanupAction;
        CleanupReference(Object referent, Runnable cleanupAction, ReferenceQueue<? super Object> q) {
            super(referent, q);
            this.cleanupAction = cleanupAction;
        }
        void cleanup() {
            cleanupAction.run();
        }
    }
}

5.5 使用示例

public class PhantomReferenceDemo {
    public static void main(String[] args) {
        Object resource = new Object();
        // 注冊(cè)清理操作
        ResourceCleaner.register(resource, () -> 
            System.out.println("資源被回收,執(zhí)行清理操作"));
        // 取消強(qiáng)引用
        resource = null;
        // 觸發(fā)GC
        System.gc();
        // 處理清理操作
        ResourceCleaner.cleanup();
    }
}

六、ReferenceQueue的作用

引用隊(duì)列(ReferenceQueue)與軟/弱/虛引用配合使用,主要用途:

  1. 跟蹤引用狀態(tài):當(dāng)引用對(duì)象被回收時(shí),引用本身會(huì)被加入隊(duì)列
  2. 執(zhí)行后續(xù)操作:通過輪詢隊(duì)列執(zhí)行清理工作
  3. 避免引用堆積:及時(shí)清理無(wú)用的Reference對(duì)象

6.1 使用模式

ReferenceQueue<Object> queue = new ReferenceQueue<>();
WeakReference<Object> ref = new WeakReference<>(new Object(), queue);
// 在另一個(gè)線程中處理隊(duì)列
new Thread(() -> {
    try {
        while (true) {
            Reference<?> r = queue.remove();
            System.out.println("對(duì)象被回收: " + r);
            // 執(zhí)行清理操作
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}).start();

6.2 各引用類型與隊(duì)列

引用類型入隊(duì)時(shí)機(jī)典型用途
軟引用對(duì)象被回收且內(nèi)存不足緩存清理通知
弱引用對(duì)象被回收WeakHashMap維護(hù)
虛引用對(duì)象被回收資源精確釋放

七、四種引用的對(duì)比總結(jié)

7.1 特性對(duì)比表

特性強(qiáng)引用軟引用弱引用虛引用
回收強(qiáng)度不回收內(nèi)存不足時(shí)回收下次GC回收隨時(shí)可能回收
get()返回值對(duì)象本身對(duì)象本身(回收前)對(duì)象本身(回收前)始終null
引用隊(duì)列不支持支持支持必須配合使用
典型用途普通對(duì)象引用內(nèi)存敏感緩存規(guī)范化映射資源清理跟蹤
實(shí)現(xiàn)類-SoftReferenceWeakReferencePhantomReference

7.2 生命周期圖示

八、實(shí)際應(yīng)用場(chǎng)景

8.1 緩存實(shí)現(xiàn)選擇

強(qiáng)引用緩存

Map<String, Object> cache = new HashMap<>(); // 可能內(nèi)存泄漏

軟引用緩存

Map<String, SoftReference<Object>> cache = new HashMap<>(); // 自動(dòng)釋放

弱引用緩存

Map<String, WeakReference<Object>> cache = new HashMap<>(); // 短期緩存

8.2 監(jiān)聽器管理

public class ListenerManager {
    private final Map<EventListener, WeakReference<Listener>> listeners = new WeakHashMap<>();
    public void addListener(EventListener listener) {
        listeners.put(listener, new WeakReference<>(listener));
    }
    // 無(wú)需顯式移除,GC會(huì)自動(dòng)清理
}

8.3 資源清理最佳實(shí)踐

public class ResourceHolder implements AutoCloseable {
    private final Object resource;
    private final PhantomReference<Object> phantomRef;
    public ResourceHolder(Object resource) {
        this.resource = resource;
        this.phantomRef = new PhantomReference<>(resource, cleanupQueue);
    }
    @Override
    public void close() {
        // 顯式清理
        cleanupResource(resource);
    }
    // 防止忘記調(diào)用close()
    protected void finalize() throws Throwable {
        if (resource != null) {
            cleanupResource(resource);
        }
    }
    private static void cleanupResource(Object resource) {
        // 實(shí)際清理邏輯
    }
}

九、常見問題與解決方案

9.1 內(nèi)存泄漏診斷

問題:即使使用弱引用,內(nèi)存仍在增長(zhǎng)

解決方案

  1. 檢查是否有強(qiáng)引用意外保留
  2. 確保正確使用ReferenceQueue清理
  3. 使用MAT等工具分析內(nèi)存快照

9.2 引用隊(duì)列處理延遲

問題:對(duì)象已回收但引用未入隊(duì)

解決方案

  1. 確保有活躍線程處理隊(duì)列
  2. 適當(dāng)調(diào)用System.gc()(僅測(cè)試環(huán)境)
  3. 增加內(nèi)存壓力觸發(fā)GC

9.3 緩存性能優(yōu)化

問題:軟引用緩存頻繁重建

解決方案

  1. 調(diào)整JVM內(nèi)存參數(shù)(-Xmx)
  2. 實(shí)現(xiàn)多級(jí)緩存(強(qiáng)引用+軟引用)
  3. 使用專業(yè)緩存庫(kù)(Caffeine, Ehcache)

十、總結(jié)

Java的四種引用類型提供了不同層次的對(duì)象生命周期控制:

  1. 強(qiáng)引用:默認(rèn)選擇,確保對(duì)象長(zhǎng)期存活
  2. 軟引用:實(shí)現(xiàn)內(nèi)存敏感緩存,平衡性能與內(nèi)存使用
  3. 弱引用:避免干預(yù)GC行為,適合規(guī)范化映射
  4. 虛引用:最精細(xì)的回收跟蹤,用于資源清理

正確運(yùn)用這些引用類型可以:

  • 預(yù)防內(nèi)存泄漏
  • 優(yōu)化內(nèi)存使用
  • 實(shí)現(xiàn)高效的緩存策略
  • 精確控制資源生命周期

理解這些引用類型的差異和適用場(chǎng)景,是成為Java高級(jí)開發(fā)者的重要一步。在實(shí)際開發(fā)中,應(yīng)根據(jù)具體需求選擇合適的引用類型,并配合ReferenceQueue等機(jī)制實(shí)現(xiàn)健壯的內(nèi)存管理。

到此這篇關(guān)于Java中的四種引用類型之強(qiáng)引用、軟引用、弱引用和虛引用及用法詳解的文章就介紹到這了,更多相關(guān)java 強(qiáng)引用 軟引用 弱引用和虛引用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解mybatis批量插入10萬(wàn)條數(shù)據(jù)的優(yōu)化過程

    詳解mybatis批量插入10萬(wàn)條數(shù)據(jù)的優(yōu)化過程

    這篇文章主要介紹了詳解mybatis批量插入10萬(wàn)條數(shù)據(jù)的優(yōu)化過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 詳解Java如何實(shí)現(xiàn)防止惡意注冊(cè)

    詳解Java如何實(shí)現(xiàn)防止惡意注冊(cè)

    惡意注冊(cè)通常是指使用自動(dòng)化腳本或者機(jī)器人在短時(shí)間內(nèi)進(jìn)行大量的注冊(cè)行為,這種行為會(huì)對(duì)系統(tǒng)造成壓力,甚至?xí)?dǎo)致系統(tǒng)癱瘓。所以本文為大家總結(jié)了一些防止惡意注冊(cè)的方法,需要的可以參考一下
    2023-04-04
  • Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例

    Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例

    這篇文章主要介紹了Zookeeper實(shí)現(xiàn)分布式鎖代碼實(shí)例,Zookeeper?分布式鎖應(yīng)用了其?臨時(shí)順序節(jié)點(diǎn)?的特性,在Zookeeper中創(chuàng)建一個(gè)持久節(jié)點(diǎn)ParentLock,當(dāng)?shù)谝粋€(gè)客戶端要獲取鎖時(shí),在ParentLock節(jié)點(diǎn)下創(chuàng)建一個(gè)臨時(shí)順序節(jié)點(diǎn),需要的朋友可以參考下
    2023-12-12
  • ConcurrentMap.putIfAbsent(key,value)用法實(shí)例

    ConcurrentMap.putIfAbsent(key,value)用法實(shí)例

    這篇文章主要介紹了ConcurrentMap.putIfAbsent(key,value)用法實(shí)例,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式

    Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式

    這篇文章主要介紹了Java 延遲隊(duì)列的常用的實(shí)現(xiàn)方式,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-04-04
  • java二路歸并排序示例分享

    java二路歸并排序示例分享

    這篇文章主要介紹了java二路歸并排序示例,需要的朋友可以參考下
    2014-02-02
  • 使用Mybatis遇到的there is no getter異常

    使用Mybatis遇到的there is no getter異常

    這篇文章主要介紹了使用Mybatis遇到的there is no getter異常,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • Java實(shí)現(xiàn)簡(jiǎn)單的日歷界面

    Java實(shí)現(xiàn)簡(jiǎn)單的日歷界面

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡(jiǎn)單的日歷界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java幾種常用JSON庫(kù)性能比較詳解

    Java幾種常用JSON庫(kù)性能比較詳解

    這篇文章主要介紹了Java幾種常用JSON庫(kù)性能比較詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-06-06
  • java統(tǒng)計(jì)字符串中指定元素出現(xiàn)次數(shù)方法

    java統(tǒng)計(jì)字符串中指定元素出現(xiàn)次數(shù)方法

    這篇文章主要介紹了java統(tǒng)計(jì)字符串中指定元素出現(xiàn)次數(shù)方法,需要的朋友可以參考下
    2015-12-12

最新評(píng)論

石景山区| 达尔| 金堂县| 鹤峰县| 台中县| 多伦县| 鄂托克前旗| 龙门县| 郎溪县| 瑞金市| 霍州市| 皋兰县| 社会| 越西县| 石首市| 辽阳市| 育儿| 冕宁县| 丰城市| 南开区| 都匀市| 青岛市| 正蓝旗| 张家界市| 嘉义县| 亳州市| 甘孜| 龙山县| 门头沟区| 皮山县| 花垣县| 鄂温| 宁阳县| 玉林市| 彭水| 和林格尔县| 嘉祥县| 新宁县| 太白县| 达孜县| 马公市|