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

Java資源管理和引用體系的使用詳解

 更新時(shí)間:2025年05月13日 11:12:30   作者:找不到、了  
這篇文章主要介紹了Java資源管理和引用體系的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Java中的引用類型不僅是內(nèi)存管理的概念,更是資源管理的重要工具。合理使用不同類型的引用可以有效地管理內(nèi)存敏感資源,防止內(nèi)存泄漏和資源浪費(fèi)。

1、java的引用體系

如下圖所示,可分為四種:強(qiáng)引用、軟引用、弱引用和虛引用。

以下是對(duì)四種引用的類比,可以讓大家有個(gè)更好的理解。

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

基本特性

Object obj = new Object(); // 這就是強(qiáng)引用
  • 默認(rèn)引用類型:所有普通對(duì)象引用都是強(qiáng)引用。
  • GC行為:只要強(qiáng)引用存在,對(duì)象就不會(huì)被回收。
  • 內(nèi)存泄漏:無意保留的強(qiáng)引用是內(nèi)存泄漏的主因。

代碼示例:

public class StrongReferenceExample {
    private List<String> cache = new ArrayList<>();
    
    public void addToCache(String data) {
        cache.add(data); // 強(qiáng)引用保留對(duì)象
    }
    
    public void clearCache() {
        cache.clear(); // 必須顯式清除
    }
}

2、軟引用 (Soft Reference)

1.基本特性

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

GC行為

  • 內(nèi)存充足時(shí):保留對(duì)象
  • 內(nèi)存不足時(shí):回收對(duì)象(在OOM之前)
  • 緩存特性:適合實(shí)現(xiàn)內(nèi)存敏感緩存

2.核心特點(diǎn)

  • 動(dòng)態(tài)調(diào)整緩存大小
  • 當(dāng)系統(tǒng)內(nèi)存充足時(shí),可以緩存更多數(shù)據(jù)以提高性能
  • 當(dāng)內(nèi)存緊張時(shí),自動(dòng)清理部分緩存,避免內(nèi)存溢出

優(yōu)先級(jí)管理

  • 對(duì)緩存項(xiàng)設(shè)置優(yōu)先級(jí)(如LRU最近最少使用)
  • 內(nèi)存不足時(shí)優(yōu)先清理低優(yōu)先級(jí)數(shù)據(jù)

3.響應(yīng)內(nèi)存壓力

  • 監(jiān)聽JVM內(nèi)存使用情況(如 Runtime.getRuntime().freeMemory())。
  • 或使用 Java.lang.ref.SoftReference(軟引用)讓GC在內(nèi)存不足時(shí)自動(dòng)回收。
  • 實(shí)現(xiàn)方式

實(shí)戰(zhàn)示例:基于內(nèi)存壓力softReference的圖片緩存

public class ImageCache {
    private final Map<String, SoftReference<Bitmap>> cache = new HashMap<>();
    
    public Bitmap getImage(String key) {
        SoftReference<Bitmap> ref = cache.get(key);
        return ref != null ? ref.get() : null;
    }
    
    public void putImage(String key, Bitmap image) {
        cache.put(key, new SoftReference<>(image));
    }
}

基于Runtime.freeMemoy()來實(shí)現(xiàn)。

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

public class MemorySensitiveCache<K, V> {
    private final Map<K, SoftReference<V>> cache = new HashMap<>();

    // 存入緩存(使用軟引用,內(nèi)存不足時(shí)可被GC回收)
    public void put(K key, V value) {
        cache.put(key, new SoftReference<>(value));
    }

    // 從緩存讀?。赡芊祷豱ull如果已被GC回收)
    public V get(K key) {
        SoftReference<V> ref = cache.get(key);
        return (ref != null) ? ref.get() : null;
    }

    // 示例:內(nèi)存監(jiān)控線程
    public void startMemoryMonitor() {
        new Thread(() -> {
            while (true) {
                long freeMem = Runtime.getRuntime().freeMemory();
                if (freeMem < 1024 * 1024) { // 如果剩余內(nèi)存 < 1MB
                    System.out.println("內(nèi)存緊張,清理緩存...");
                    cache.clear();
                }
                try { Thread.sleep(1000); } catch (InterruptedException e) {}
            }
        }).start();
    }
}

3、弱引用 (Weak Reference)

3.1、基本特性

  • GC行為下次GC時(shí)立即回收(無論內(nèi)存是否充足)
  • 規(guī)范映射:適合存儲(chǔ)元數(shù)據(jù)等輔助信息
WeakReference<Object> weakRef = new WeakReference<>(new Object());

代碼示例:

import java.util.WeakHashMap;

public class WeakHashMapExample {
    public static void main(String[] args) {
        WeakHashMap<Object, String> map = new WeakHashMap<>();
        
        Object key = new Object();
        map.put(key, "Value");
        
        System.out.println("GC 前: " + map.size()); // 1
        
        key = null; // 斷開強(qiáng)引用
        System.gc(); // 觸發(fā) GC
        
        System.out.println("GC 后: " + map.size()); // 0(Entry 被自動(dòng)清理)
    }
}

4、虛引用 (Phantom Reference)

基本特性

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

GC行為

  • 對(duì)象變得虛引用可達(dá)
  • 引用加入隊(duì)列
  • 最終回收內(nèi)存

特殊限制get()方法永遠(yuǎn)返回null

主要用途:精確控制資源清理時(shí)機(jī)

5、常見問題

Q1: WeakHashMap的key是弱引用,那value呢?

A: 只有key是弱引用,value是強(qiáng)引用。需要確保value不間接引用key,否則會(huì)內(nèi)存泄漏。

Q2: 虛引用get()為什么返回null?

A: 這是設(shè)計(jì)使然,虛引用僅用于跟蹤回收事件,不應(yīng)再訪問將死對(duì)象。

Q3: 軟引用和弱引用誰更適合緩存?

A: 軟引用適合主緩存(內(nèi)存敏感),弱引用適合輔助緩存(立即釋放)。

四種引用的區(qū)別和聯(lián)系如下圖所示:

2、finalize

finalize:垃圾回收的終結(jié)機(jī)制。

2.1、所屬領(lǐng)域

  • 垃圾回收(Garbage Collection) 的補(bǔ)充機(jī)制。
  • 屬于 java.lang.Object 的基礎(chǔ)方法,與 JVM 的 GC 流程相關(guān)。

2.2、作用

  • 在對(duì)象被垃圾回收前,JVM 會(huì)調(diào)用 finalize() 方法(如果重寫了該方法),用于執(zhí)行最后的清理操作(如關(guān)閉非內(nèi)存資源)。

2.3、問題

  • 不可靠:JVM 不保證 finalize() 的執(zhí)行時(shí)機(jī)(甚至可能不執(zhí)行)。
  • 性能開銷:拖慢 GC 效率(對(duì)象需要至少兩次 GC 才能被回收)。
  • 已被廢棄:Java 9 開始標(biāo)記為 @Deprecated,推薦用 java.lang.ref.CleanerAutoCloseable 替代。

2.4、使用場(chǎng)景

想象你租了一間房:

  • 正常情況:退租時(shí)主動(dòng)交還鑰匙(相當(dāng)于 close() 方法)
  • 忘記還鑰匙:房東最后會(huì)自己來收鑰匙(相當(dāng)于 finalize()
  • 風(fēng)險(xiǎn):房東可能很久后才來,期間鑰匙被別人撿到可能不安全

代碼示例:

public class Room {
    private static final Set<String> LEAKED_KEYS = new HashSet<>();
    private String roomKey;

    public Room(String key) {
        this.roomKey = key;
        LEAKED_KEYS.add(key); // 登記鑰匙
        System.out.println("拿到鑰匙進(jìn)入房間: " + key);
    }

    // 主動(dòng)還鑰匙(推薦方式)
    public void returnKey() {
        if (roomKey != null) {
            System.out.println("主動(dòng)歸還鑰匙: " + roomKey);
            LEAKED_KEYS.remove(roomKey); // 注銷鑰匙
            roomKey = null;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        if (roomKey != null) {
            System.out.println("警告!鑰匙未被歸還: " + roomKey + " (內(nèi)存泄漏)");
            LEAKED_KEYS.remove(roomKey); // 清理登記
        }
    }

    public static void main(String[] args) {
        // 好租客
        Room goodRoom = new Room("A101");
        goodRoom.returnKey();

        // 壞租客
        new Room("B202"); // 直接不保存引用
        
        System.gc();
        try { Thread.sleep(1000); } catch (Exception e) {}
        
        System.out.println("未歸還的鑰匙: " + LEAKED_KEYS);
    }
}

輸出:

拿到鑰匙進(jìn)入房間: A101
主動(dòng)歸還鑰匙: A101
拿到鑰匙進(jìn)入房間: B202
警告!鑰匙未被歸還: B202 (內(nèi)存泄漏)
未歸還的鑰匙: []

結(jié)論

  • finalize() 只會(huì)在 GC 回收對(duì)象時(shí)執(zhí)行,而 System.gc() 只是建議 GC 運(yùn)行,不保證立即執(zhí)行。
  • finalize() 不保證一定執(zhí)行,如果程序退出前 GC 沒運(yùn)行,它就不會(huì)被調(diào)用。
  • 不應(yīng)該依賴 finalize() 管理資源(如文件、數(shù)據(jù)庫連接),而應(yīng)該使用 try-with-resources 或手動(dòng) close()。
  • 同步調(diào)用 finalize() 會(huì)阻塞 GC 線程,降低性能。

3、try-with-resources

屬于java的資源管理 → try-with-resources + AutoCloseable。

3.1、所屬領(lǐng)域

  • 資源管理(Resource Management),尤其是需要顯式釋放的資源(如文件、數(shù)據(jù)庫連接、網(wǎng)絡(luò)套接字)。
  • 基于 AutoCloseable 接口(Java 7 引入),屬于語法糖(Syntactic Sugar)。

3.2、作用

  • 自動(dòng)在 try 代碼塊結(jié)束后調(diào)用資源的 close() 方法,避免資源泄露
  • 比手動(dòng) try-catch-finally 更簡(jiǎn)潔安全。

3.3、優(yōu)勢(shì)

  • 確定性釋放:資源離開 try 塊立即關(guān)閉。
  • 代碼簡(jiǎn)潔:減少嵌套和樣板代碼。
  • 異常友好:支持抑制異常(Suppressed Exceptions)。

代碼示例:

// 實(shí)現(xiàn) AutoCloseable,用 try-with-resources 確保資源釋放
class Resource implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Resource closed!");
    }
}

public class Main {
    public static void main(String[] args) {
        try (Resource r = new Resource()) {
            // 使用資源
        } // 自動(dòng)調(diào)用 close()
    }
}

finalize和try-with-resources的區(qū)別如下圖所示:

替代 finalize 的方案:

  • CleanerPhantomReference:提供更可控的清理機(jī)制(但復(fù)雜度高)。
  • AutoCloseable + try-with-resources:首選方案。

資源管理的最佳實(shí)踐

  • 優(yōu)先實(shí)現(xiàn) AutoCloseable 接口,而非依賴 finalize。
  • 對(duì)于必須手動(dòng)管理的資源(如原生內(nèi)存),結(jié)合 ByteBuffer.allocateDirectCleaner 使用。

4、Cleaner

(Java 9+)java.lang.ref.Cleaner。

如下圖所示 :由phant虛引用和隊(duì)列來實(shí)現(xiàn)。

4.1、Cleaner 的優(yōu)勢(shì)

? 確定性更強(qiáng):通過虛引用(PhantomReference)和引用隊(duì)列實(shí)現(xiàn)

? 更安全:清理操作在獨(dú)立線程執(zhí)行,不影響主線程

? 性能更好:不干擾正常垃圾回收流程

? 可控性高:可以顯式注冊(cè)/取消清理操作

4.2、底層機(jī)制

  • 引用類型:使用 PhantomReference(虛引用)
  • 引用隊(duì)列:被清理對(duì)象進(jìn)入引用隊(duì)列時(shí)觸發(fā)清理
  • 守護(hù)線程:專門的清理線程處理隊(duì)列中的對(duì)象

代碼示例如下:

// Cleaner 內(nèi)部實(shí)現(xiàn)偽代碼
public class Cleaner {
    private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
    private final PhantomReference<Object> phantomRef;
    private final Runnable cleanupAction;
    
    public static Cleaner create() {
        return new Cleaner();
    }
    
    public Cleanable register(Object obj, Runnable action) {
        phantomRef = new PhantomReference<>(obj, queue);
        this.cleanupAction = action;
        startCleanerThread();  // 啟動(dòng)監(jiān)控線程
        return new CleanableImpl();
    }
    
    private void startCleanerThread() {
        Thread thread = new Thread(() -> {
            while (true) {
                Reference<?> ref = queue.remove(); // 阻塞等待
                if (ref == phantomRef) {
                    cleanupAction.run();
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
}

4.3、執(zhí)行流程

import java.lang.ref.Cleaner;

public class CleanerDemo {
    private static final Cleaner cleaner = Cleaner.create();

    static class Resource implements Runnable {
        @Override
        public void run() {
            System.out.println("Cleaner action executed!");
        }
    }

    public static void main(String[] args) {
        Resource resource = new Resource();
        cleaner.register(new Object(), resource); // 注冊(cè)清理動(dòng)作
        System.gc();
        try { Thread.sleep(1000); } catch (InterruptedException e) {}
    }
}

相比較于finalize和cleaner的區(qū)別:

總結(jié)

通過合理組合這些引用類型,可以構(gòu)建出既高效又安全的資源管理系統(tǒng)。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 圖解Java排序算法之快速排序的三數(shù)取中法

    圖解Java排序算法之快速排序的三數(shù)取中法

    這篇文章主要為大家詳細(xì)介紹了Java排序算法之快速排序的三數(shù)取中法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • java實(shí)現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作

    java實(shí)現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作

    這篇文章主要介紹了java實(shí)現(xiàn)相同屬性名稱及相似類型的pojo、dto、vo等互轉(zhuǎn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • maven父子工程中的依賴引用的實(shí)現(xiàn)

    maven父子工程中的依賴引用的實(shí)現(xiàn)

    本文主要介紹了Maven父子工程中的依賴引用的實(shí)現(xiàn),包括<dependencyManagement>和<dependencies>兩個(gè)標(biāo)簽的使用,以及父子pom文件的配置,感興趣的可以了解一下
    2024-10-10
  • 如何使用java修改文件所有者及其權(quán)限

    如何使用java修改文件所有者及其權(quán)限

    這篇文章主要介紹了如何使用java修改文件所有者及其權(quán)限,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Elasticsearch term 查詢之精確值搜索功能實(shí)現(xiàn)

    Elasticsearch term 查詢之精確值搜索功能實(shí)現(xiàn)

    term查詢是Elasticsearch中用于精確值搜索的一種基本方式,通過了解 term 查詢的工作原理和使用方法,你可以更好地利用 Elasticsearch 進(jìn)行結(jié)構(gòu)化數(shù)據(jù)的搜索和分析,本文將詳細(xì)介紹 term 查詢的工作原理、使用場(chǎng)景以及如何在 Elasticsearch 中應(yīng)用它,感興趣的朋友一起看看吧
    2024-06-06
  • 如何在Spring中使用編碼方式動(dòng)態(tài)配置Bean詳解

    如何在Spring中使用編碼方式動(dòng)態(tài)配置Bean詳解

    這篇文章主要給大家介紹了關(guān)于如何在Spring中使用編碼方式動(dòng)態(tài)配置Bean的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • SpringBoot中的自定義FailureAnalyzer詳解

    SpringBoot中的自定義FailureAnalyzer詳解

    這篇文章主要介紹了SpringBoot中的自定義FailureAnalyzer詳解,FailureAnalyzer是一種很好的方式在啟動(dòng)時(shí)攔截異常并將其轉(zhuǎn)換為易讀的消息,并將其包含在FailureAnalysis中, Spring Boot為應(yīng)用程序上下文相關(guān)異常、JSR-303驗(yàn)證等提供了此類分析器,需要的朋友可以參考下
    2023-12-12
  • 淺談Java并發(fā)之同步器設(shè)計(jì)

    淺談Java并發(fā)之同步器設(shè)計(jì)

    這篇文章主要介紹Java并發(fā)之同步器設(shè)計(jì),本文以記錄方式并發(fā)編程中同步器設(shè)計(jì)的一些共性特征。并簡(jiǎn)單介紹了Java中的AQS,需要的朋友可以參考一下文章的詳細(xì)內(nèi)容
    2021-10-10
  • java音樂播放器實(shí)現(xiàn)代碼

    java音樂播放器實(shí)現(xiàn)代碼

    這篇文章主要介紹了java音樂播放器的實(shí)現(xiàn)代碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • 詳解Java運(yùn)算中的取余

    詳解Java運(yùn)算中的取余

    這篇文章主要介紹了java運(yùn)算中的取余,在java運(yùn)算中,取余符號(hào)是?%,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05

最新評(píng)論