Java中的软引用,你了解吗?

news2024/11/17 19:39:14

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

在Java中,垃圾回收是一个非常重要的概念。为了防止内存泄漏和程序的性能问题,Java中对于对象的垃圾回收进行了优化和改进。其中,软引用就是垃圾回收的一种方式。本文将介绍Java中的软引用,其基本概念以及如何在实际应用中使用软引用

摘要

本文将深入探讨Java中的软引用,包括其定义和使用。我们将介绍如何使用软引用来避免内存泄漏和优化程序性能。本文还将提供源代码解析,应用场景案例以及优缺点分析,以便读者更好地理解软引用的特点和使用方法。

软引用

简介

在Java中,垃圾回收是一种自动化的内存管理机制。Java垃圾回收器会自动查找不再使用的对象并将其释放回内存供重用。软引用是Java中一种机制,用于保留对对象的引用,但允许该对象被垃圾回收器回收。软引用可以帮助程序员更精细地控制内存的使用,节省程序资源并提高程序性能。

软引用对象可以通过java.lang.ref.SoftReference类创建。SoftReference对象允许程序员保留对对象的引用,但允许该对象被垃圾回收器回收。当Java虚拟机需要内存时,垃圾回收器将会回收由软引用指向的对象。软引用可以用于缓存,使得垃圾回收器在内存不足时可以回收该对象,从而避免内存泄漏。

源代码解析

下面是一个简单的Java代码例子,演示如何使用软引用:

import java.lang.ref.SoftReference;

public class SoftReferenceExample {
    public static void main(String[] args) {
        Object obj = new Object();
        SoftReference<Object> softRef = new SoftReference<Object>(obj);
        obj = null;
        System.gc();
        if (softRef.get() != null) {
            System.out.println("Object is still available");
        } else {
            System.out.println("Object has been collected");
        }
    }
}

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  1. 创建一个Object对象,然后创建一个SoftReference对象来引用该Object对象。

  2. obj变量赋一个null值,这表示原来的Object对象已经没有指向它的引用了,只有软引用对象持有它的引用。

  3. 调用System.gc()方法,手动通知垃圾回收器回收不再使用的对象。

  4. 如果软引用对象的get()方法返回null,表示原来的Object对象已经被回收;否则,表示原来的Object对象仍然可用。

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

在这里插入图片描述

应用场景案例

软引用可以用于缓存、图片处理等方面,以避免内存泄漏和优化程序性能。下面是两个Java使用软引用的实际案例:

缓存

在Java中,缓存是一种常见的性能优化技术。使用软引用可以避免缓存对象过多占用内存。当内存不足时,垃圾回收器将会回收软引用指向的对象。下面是一个简单的缓存实现:

package com.example.javase.se.classes.softReference;

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

/**
 * @Author ms
 * @Date 2023-11-05 21:52
 */
public class Cache {

    private Map<String, SoftReference<Object>> cacheMap;

    public Cache() {
        this.cacheMap = new HashMap<String, SoftReference<Object>>();
    }

    public void put(String key, Object value) {
        cacheMap.put(key, new SoftReference<Object>(value));
    }

    public Object get(String key) {
        Object obj = null;
        SoftReference<Object> softRef = cacheMap.get(key);
        if (softRef != null) {
            obj = softRef.get();
        }
        return obj;
    }

    public void clear() {
        cacheMap.clear();
    }
}

说明:

  1. 构造方法创建一个Map对象,用于存储软引用对象。

  2. put()方法将软引用对象添加到Map对象中。

  3. get()方法从Map对象中获取软引用对象,通过get()方法获取原始对象。

  4. clear()方法清空Map对象。

图片处理

在Java中,处理大量图片可能会导致内存泄漏和程序性能低下。使用软引用可以避免占用过多的内存,并提高程序性能。下面是一个简单的Java代码例子,演示如何使用软引用来缓存图片:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import javax.imageio.ImageIO;

public class ImageCache {
    private static final String IMAGE_DIR = "images/";
    private static Map<String, SoftReference<BufferedImage>> imageCache = new HashMap<String, SoftReference<BufferedImage>>();
    public static BufferedImage getImage(String fileName) {
        SoftReference<BufferedImage> soft = imageCache.get(fileName);
        if (soft != null) {
            BufferedImage image = soft.get();
            if (image != null) {
                return image;
            }
        }
        File file = new File(IMAGE_DIR + fileName);
        try {
            BufferedImage image = ImageIO.read(file);
            imageCache.put(fileName, new SoftReference<BufferedImage>(image));
            return image;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

说明:

  1. getImage()方法从imageCache中获取指定文件名对应的图像。如果软引用对象存在,就从软引用中获取BufferedImage对象;否则,就从磁盘中读取图像。

  2. 当软引用对象被回收时,JVM将自动从磁盘中读取图像。

优缺点分析

软引用的优点:

  1. 对象可以被垃圾回收器回收,避免内存泄漏。

  2. 可以用于缓存、图片处理等方面,以优化程序性能。

  3. 不会影响程序的正常运行。

软引用的缺点:

  1. 对象的生命周期难以控制,容易被回收。

  2. 软引用对象不能被强制保留,可能会造成性能问题。

  3. 对象被回收后,重新获取时可能会影响程序性能。

类代码方法介绍

java.lang.ref.SoftReference类

public class SoftReference<T> extends Reference<T>

该类继承自Reference类,用于创建软引用对象。可以在Java中使用该类来实现软引用。

方法:

  1. get():返回由此软引用对象所引用的对象。

Cache类

public class Cache {
    private Map<String, SoftReference<Object>> cacheMap;
    public Cache();
    public void put(String key, Object value);
    public Object get(String key);
    public void clear();
}

说明:

  1. 构造方法用于创建Cache对象,并创建一个Map对象,用于存储软引用对象。

  2. put()方法将软引用对象添加到Map对象中。

  3. get()方法从Map对象中获取软引用对象,通过get()方法获取原始对象。

  4. clear()方法清空Map对象。

ImageCache类

public class ImageCache {
    private static final String IMAGE_DIR = "images/";
    private static Map<String, SoftReference<BufferedImage>> imageCache = new HashMap<String, SoftReference<BufferedImage>>();
    public static BufferedImage getImage(String fileName);
}

说明:

  1. getImage()方法从imageCache中获取指定文件名对应的图像。如果软引用对象存在,就从软引用中获取BufferedImage对象;否则,就从磁盘中读取图像。

测试用例

下面是一个简单的测试用例,演示如何使用软引用来避免内存泄漏和优化程序性能:

public class TestSoftReference {

    public static void main(String[] args) {
        // 创建一个字符串对象并赋值"hello"
        String str = new String("hello");
        // 创建一个软引用,指向该字符串对象
        SoftReference<String> softRef = new SoftReference<String>(str);
        // 将原字符串对象引用置为null
        str = null;
        // 手动触发垃圾回收
        System.gc();
        // 判断软引用是否还指向对象
        if (softRef.get() != null) {
            System.out.println("软引用对象未被回收,内容为:" + softRef.get());
        } else {
            System.out.println("软引用对象已被回收");
        }
    }

}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

运行结果:

软引用对象未被回收,内容为:hello

在这里插入图片描述

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

这段代码演示了软引用的基本用法。首先创建了一个字符串对象并赋值"hello",然后创建一个软引用 softRef,指向该字符串对象。接着将原字符串对象 str 引用置为 null,这是为了让该对象成为垃圾对象。然后手动触发垃圾回收,这会触发 JVM 进行垃圾回收。

最后判断软引用是否还指向对象。如果 softRef.get() 不为 null,则说明软引用对象未被回收,打印 “软引用对象未被回收,内容为:” + softRef.get(),内容为 hello;否则说明软引用对象已被回收,打印 “软引用对象已被回收”。

可以通过改变 JVM 参数来观察软引用对象的回收情况。

SoftReference 是 JVM 提供的一种基本的引用类型,在内存充足时表现和普通强引用一样,但在内存不足时,会被 GC 回收,避免 OutOfMemoryError 异常。

继续看下一个测试用例,这次我们将创建一个缓存类来存储软引用对象:

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

public class Cache {

    private Map<String, SoftReference<Object>> cacheMap;

    public Cache() {
        cacheMap = new HashMap<>();
    }

    public void put(String key, Object value) {
        SoftReference<Object> softRef = new SoftReference<Object>(value);
        cacheMap.put(key, softRef);
    }

    public Object get(String key) {
        SoftReference<Object> softRef = cacheMap.get(key);
        if (softRef != null) {
            return softRef.get();
        }
        return null;
    }

    public void clear() {
        cacheMap.clear();
    }

}

该缓存类的实现很简单,使用Map来存储软引用对象,put()方法用于添加软引用对象,get()方法用于获取原始对象,clear()方法用于清空缓存。接下来,我们来测试该缓存类的使用:

public class TestCache {

    public static void main(String[] args) {
        // 创建一个缓存对象
        Cache cache = new Cache();
        // 缓存一个字符串对象
        String str = new String("hello");
        cache.put("str", str);
        // 将原字符串对象引用置为null
        str = null;
        // 手动触发垃圾回收
        System.gc();
        // 从缓存中获取字符串对象
        String cacheStr = (String) cache.get("str");
        // 判断缓存对象是否为空
        if (cacheStr != null) {
            System.out.println("从缓存中获取到对象:" + cacheStr);
        } else {
            System.out.println("缓存中不存在该对象");
        }
    }

}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

运行结果:

从缓存中获取到对象:hello

在这里插入图片描述

在这个示例中,我们使用Cache类来缓存一个字符串对象,并将原字符串对象的引用置为null,手动触发垃圾回收。接着,从缓存中获取字符串对象,判断缓存对象是否为空。由于该缓存对象仍然指向该字符串对象,所以从缓存中成功获取到了该对象。

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

该程序演示了使用软引用实现缓存功能。主要流程如下:

  1. 创建一个 Cache 对象,用于缓存对象。
  2. 创建一个字符串对象 “hello”,并调用 Cache 对象的 put 方法将其保存到缓存中。
  3. 将字符串对象的引用 str 置为 null。
  4. 手动触发垃圾回收,此时会触发软引用对象的回收。
  5. 从缓存中获取字符串对象并赋值给变量 cacheStr。
  6. 判断 cacheStr 是否为空,如果不为空则表示从缓存中获取到了字符串对象。

因为字符串对象被缓存后,只有缓存对象持有其软引用,当内存不足时,垃圾回收器会根据对象的引用类型及其占用内存的大小来进行垃圾回收。软引用可以在内存不足时被垃圾回收器回收,但要避免在内存足够的时候就被回收,否则就失去了缓存的意义。因此,这种方式适合缓存占用内存比较大、但不需要长时间保存的对象。

小结

软引用是Java中一种垃圾回收的方式,可以用于避免内存泄漏和优化程序性能。在Java中,可以通过SoftReference类来创建软引用对象,并可用于缓存、图片处理等方面。使用软引用可以更精细地控制内存的使用,避免内存泄漏和提高程序性能。在使用软引用时,需要注意对象的生命周期和软引用对象是否被回收。

总结

本文介绍了Java中的软引用,包括其定义、源代码解析、应用场景案例和优缺点分析。软引用是一种垃圾回收的方式,可以保留对对象的引用,但允许该对象被垃圾回收器回收,避免内存泄漏和优化程序性能。可以使用java.lang.ref.SoftReference类来创建软引用对象,并可用于缓存、图片处理等方面。需要注意对象的生命周期和软引用对象是否被回收,以便更好地控制内存的使用。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1721400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

打工人福音,办公神器软件

今天分享2个免VIP的办公神器app&#xff0c;建议所有手机安装&#xff0c;第一个布丁扫描http://www.budingscan.com &#xff0c;无广告不收费&#xff0c;这是VIVO 推出的一款完全免费的扫描APP&#xff0c;支持文档&#xff06;证件扫描、OCR文字&#xff06;表格识别提取、…

解决Windows 10通过SSH连接Ubuntu 20.04时的“Permission Denied”错误

在使用SSH连接远程服务器时&#xff0c;我们经常可能遇到各种连接错误&#xff0c;其中“Permission denied, please try again”是较为常见的一种。本文将分享一次实际案例的解决过程&#xff0c;帮助你理解如何排查并解决这类问题。 问题描述 在尝试从Windows 10系统通过SS…

js:flex弹性布局

目录 代码&#xff1a; 1、 flex-direction 2、flex-wrap 3、justify-content 4、align-items 5、align-content 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewp…

Mysql基础教程(13):GROUP BY

MySQL GROUP BY 【 GROUP BY】 子句用于将结果集根据指定的字段或者表达式进行分组。 有时候&#xff0c;我们需要将结果集按照某个维度进行汇总。这在统计数据的时候经常用到&#xff0c;考虑以下的场景&#xff1a; 按班级求取平均成绩。按学生汇总某个人的总分。按年或者…

【spring】Spring Boot3.3.0发布啦

spring最新版本 springboot官网&#xff1a;Spring Boot :: Spring Boot Spring Boot 3.3 发行说明&#xff1a;https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.3-Release-Notes 开发环境的要求对比表 Spring BootJDKSpringMavenGradle3.3.017 ~ 226.1…

Nginx实战:LUA脚本_环境配置安装

目录 一、什么是LUA脚本 二、Nginx中的LUA脚本 1、主要特点 2、用途 三、如何在nginx中使用LUA脚本 1、原生nginx 2、OpenResty 3、nginx lua配置验证 一、什么是LUA脚本 Nginx Lua 脚本是 Nginx 与 Lua 语言集成的结果&#xff0c;它允许你使用 Lua 语言编写Nginx 模块…

【Redis】List源码剖析

大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#xff0c;但是也想日更的人。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4aa;&#x1f4aa;&#x1f4aa…

使用第三方工具percona-xtrabackup进行数据备份与恢复

目录 准备工作 开始安装 innobackupex的使用 完全备份 增量备份 数据恢复 本次需要用到的软件 mysql 5.7.35percona-xtrabackup-24-2.4.8 ps&#xff1a;---MySQL必须是5.7的版本&#xff0c;在8.0之后已经不支持 percona-xtrabackup-24 系统版本CentOS7.9 准备工作 …

面试题 17.05. 字母与数字(前缀和)

给定一个放有字母和数字的数组&#xff0c;找到最长的子数组&#xff0c;且包含的字母和数字的个数相同。 返回该子数组&#xff0c;若存在多个最长子数组&#xff0c;返回左端点下标值最小的子数组。若不存在这样的数组&#xff0c;返回一个空数组。 示例 1: 输入: ["…

SpringBoot+layui实现Excel导入操作

excel导入步骤 第三方插件引入插件 效果图 &#xff08;方法1&#xff09;代码实现&#xff08;方法1&#xff09;Html代码&#xff08; 公共&#xff09;下载导入模板 js实现 &#xff08;方法1&#xff09;上传文件实现 效果图&#xff08;方法2&#xff09;代码实现&#xf…

一碗米线火了24年,蒙自源六一再献新作

当一碗热气腾腾的米线在餐桌上飘香四溢&#xff0c;你是否会想起那个陪伴了无数食客24年的名字——蒙自源&#xff1f;在这个充满欢笑与童真的六一儿童节&#xff0c;蒙自源米线品牌再度发力&#xff0c;用全新的儿童餐系列为孩子们带来了一份特别的节日礼物。 蒙自源&#xf…

性价比为王,物流商怎么选择高效的国际物流管理平台

在全球化贸易日益繁荣的今天&#xff0c;国际物流行业作为链接国内商家和海外市场的重要桥梁&#xff0c;发挥着极其重要的作用。 然而&#xff0c;随着国际物流市场竞争的加剧&#xff0c;对物流商来说&#xff0c;也面临着成本管控和效率提升的双重挑战。今天我们会重点探讨…

AI之下 360让PC商业生态大象起舞

时隔7年&#xff0c;淘宝PC版在前不久迎来重磅升级&#xff0c;在产品体验、商品供给、内容供给等方面做了全面优化&#xff0c;以全面提升PC端的用户体验&#xff1b;当大家都以为移动互联网时代下APP将成为主流时&#xff0c;PC端却又成为了香饽饽。其实PC端被重视&#xff0…

【Qt】【模型视图架构】代理模型示例

文章目录 1. 基本排序/过滤模型Basic Sort/Filter Model Example2. 自定义排序/过滤模型Custom Sort/Filter Model ExampleFilterLineEdit类定义及实现MySortFilterProxyModel类定义及实现 1. 基本排序/过滤模型Basic Sort/Filter Model Example 官方提供的基本排序/过滤模型示…

LeetCode42:接雨水

题目描述 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 代码 单调栈 class Solution { public:int trap(vector<int>& height) {stack<int> stk;int result 0;stk.push(0);for (int …

Android设备获取OAID调研和实现

什么是OAID、AAID、VAID OAID OAID是"Android ID"&#xff08;安卓ID&#xff09;的一种替代方案&#xff0c;其全称为"Open Anonymous Identifier"&#xff08;开放匿名标识符&#xff09;。 因传统的移动终端设备标识如国际移动设备识别码&#xff08;…

【Python内功心法】:深挖内置函数,释放语言潜能

文章目录 &#x1f680;一、常见内置函数&#x1f308;二、高级内置函数⭐1. enumerate函数&#x1f44a;2. eval函数❤️3. exec函数&#x1f4a5;4. eval与exec 中 globals与locals如何用☔4-1 globals 参数&#x1f3ac;4-2 locals 参数 ❤️5. filter函数&#x1f44a;6. z…

发电机组故障的原因、解决方案及解决措施

发电机组故障的原因、解决方案及解决措施可以总结如下&#xff1a; 一、故障原因 供电中断 原因&#xff1a;电网故障、线路短路或电力负荷过重等。 燃油问题 原因&#xff1a;燃油供应系统问题&#xff0c;如燃油管路堵塞、燃油质量不佳等。 轴承过热 原因&#xff1a;轴承过…

小学生四则运算练习器,用户可以选择进行加减乘除任意一项,也可以选择退出,然后每次计算后会提示正确与否,最后计算总分然后并给出评语。

⑴ 用户可以从菜单中选择某种运算进行练习。具体包括&#xff1a;加法&#xff0c;减法&#xff0c;乘法&#xff0c;除法&#xff1b;也可以退出程序. ⑵ 用户可以指定每次练习的题目数量、设置练习的总分&#xff1b; ⑶ 每小题练习后给出结果正确与否的提示&#xff1b;一…

【机器学习】智能选择的艺术:决策树在机器学习中的深度剖析

在机器学习的分类和回归问题中&#xff0c;决策树是一种广泛使用的算法。决策树模型因其直观性、易于理解和实现&#xff0c;以及处理分类和数值特征的能力而备受欢迎。本文将解释决策树算法的概念、原理、应用、优化方法以及未来的发展方向。 &#x1f680;时空传送门 &#x…