首页 > 编程语言 >Java的软引用、弱引用和强引用学习

Java的软引用、弱引用和强引用学习

时间:2024-02-06 23:32:46浏览次数:38  
标签:queue Java temp 学习 SoftNode 引用 key public

一、强引用

强引用可以直接访问目标对象,所指向的对象在任何时候都不会被系统回收,JVM宁愿抛出OOM异常也不会回收强引用所指向的对象,但是有可能会导致内存泄漏。

package learn;


/**
 * @author qx
 * @date 2024/1/5
 * @des
 */
public class Demo {
    public static void main(String[] args) {
        // 强引用
        Person person = new Person(1, "admin");
    }
}

二、软引用和弱引用

软引用:如果一个对象只具有软引用,而当前虚拟机堆内存空间足够,那么垃圾回收器不会回收它,反之机会回收这些软引用指向的对象。

弱引用:垃圾回收器一旦发现某块内存上只有弱引用,不管当前内存是否足够,那么都会回收这块内存。

三、代码实例

软引用工具类

package learn;

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

/**
 * @author qx
 * @date 2024/2/5
 * @des 软引用工具类
 */
public class SoftHashMap<K, V> extends HashMap<K, V> {
    /**
     * queue,软引用标记队列
     * <p>
     * ★★★★★★★ 解释 ★★★★★★★
     * 当SoftNode中 Value 被回收时,SoftNode 对象会被放入 queue中,以表示当前SoftNode 中的Value不存在
     * 对我们的使用好处就是,我们读取 queue 队列,取出 SoftNode对象,取出其内部的 Key
     * 以便于 temp 通过 key remove
     */
    private ReferenceQueue<V> queue;
    /**
     * 真正的map对象
     * 1、temp 内部 封装的 Node 强引用 K 和 SoftNode
     * 2、SoftNode 内部强引用K,弱引用真正的Value
     */
    private HashMap<K, SoftNode<K, V>> temp;

    public SoftHashMap() {
        queue = new ReferenceQueue<>();
        temp = new HashMap<>();
    }

    @Override
    public V get(Object key) {
        clearQueue();
        // 通过 key进行取值,如果为null,返回null,否则返回 SoftNode 软引用的值
        SoftNode softNode = temp.get(key);
        return softNode == null ? null : (V) softNode.get();
    }

    @Override
    public V put(K key, V value) {
        clearQueue();
        // 创建 SoftNode对象
        SoftNode softNode = new SoftNode(key, value, queue);
        // 返回key之前所对应的SoftNode对象,即oldSoftNode
        SoftNode oldSoftNode = temp.put(key, softNode);
        // 如果oldSoftNode为null,就返回null,否则就返回 oldSoftNode所软引用的 Value
        return oldSoftNode == null ? null : (V) oldSoftNode.get();
    }

    @Override
    public boolean containsKey(Object key) {
        clearQueue();
        return temp.containsKey(key);
    }

    @Override
    public V remove(Object key) {
        clearQueue();
        SoftNode<K, V> remove = temp.remove(key);
        return remove == null ? null : remove.get();
    }

    @Override
    public int size() {
        clearQueue();
        return temp.size();
    }

    /**
     * 通过软引用队列内的 SoftNode,获取Key,然后temp 清除此 Key
     *
     * @see ReferenceQueue poll()
     * poll() -- 类似于 stack 的pop(),移除并返回此对象
     */
    private void clearQueue() {
        SoftNode poll;
        while ((poll = (SoftNode) queue.poll()) != null) {
            temp.remove(poll.key);
        }
    }


    /**
     * 对V进行软引用的类
     *
     * @param <K> key,用于当 V 被回收后,temp 可以通过 key 进行移除
     * @param <V> Value,真正的值
     *            <p>
     *            传入的queue,用于当Value被回收后,将 SoftNode对象放入 queue中,
     *            以便于表示 某 SoftNode对象中的Value 已经被收回了。
     */
    private class SoftNode<K, V> extends SoftReference<V> {
        K key;

        public SoftNode(K k, V v, ReferenceQueue queue) {
            super(v, queue);
            key = k;
        }
    }
}

四、测试

强引用:

package learn;

import java.util.HashMap;
import java.util.Map;

/**
 * @author qx
 * @date 2024/2/5
 * @des 强引用测试
 */
public class ReferenceDemo {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        System.out.println(Integer.MAX_VALUE);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            map.put(i, "hello");
            System.out.println(i);
        }
    }
}

Java的软引用、弱引用和强引用学习_强引用

软引用:

package learn;

import java.util.HashMap;
import java.util.Map;

/**
 * @author qx
 * @date 2024/2/5
 * @des
 */
public class SoftReferenceDemo {
    public static void main(String[] args) {
        SoftHashMap<Integer, String> map = new SoftHashMap<>();
        System.out.println(Integer.MAX_VALUE);
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            map.put(i, "hello");
            System.out.println(i);
        }
    }
}

Java的软引用、弱引用和强引用学习_强引用_02

测试中可以明显的看到:

  1. 强引用时,加载的String更多,但会造成内存溢出;
  2. 弱引用时,由于弱引用的机制(内存满时会进行垃圾回收),不会造成内存溢出,但由于需要对String进行处理,所以加载的String没有强引用时多;


标签:queue,Java,temp,学习,SoftNode,引用,key,public
From: https://blog.51cto.com/u_13312531/9632807

相关文章

  • Java和JavaScript区别与联系
    区别和联系Java和JavaScript是两种不同的编程语言,尽管它们的名称相似,但它们有着不同的特性、用途和工作环境。以下是对它们之间区别与联系的详细说明:语言类型:Java:Java是一种静态类型的编程语言,意味着在编译时需要声明变量的类型,并且强调面向对象编程。JavaScript:JavaScri......
  • 2024/2/6学习进度笔记
    CPU由运算器(ALU)和控制器(CU)两大部件组成。此外,还有若干个寄存器和高速缓冲存储器及实现它们之间联系的数据、控制及状态总线。ALU用来执行算术运算、移位操作、地址运算和转换;寄存器件用于保存中间数据以及指令;CU负责对指令译码,并发出为完成每条指令所要执行的各个操作的控制信号C......
  • golang命令行cobra学习
    varrootCmd=&cobra.Command{Use:"ferry",Short:"-v",SilenceUsage:true,DisableAutoGenTag:true,Long:`ferry`,Args:func(cmd*cobra.Command,args[]string)......
  • 已解决java.lang.IllegalAccessException异常的正确解决方法,亲测有效!!!
    已解决java.lang.IllegalAccessException异常的正确解决方法,亲测有效!!!文章目录问题分析与报错原因解决思路解决方法总结 ----------------------------------------------------------------------------------------------------------------问题分析与报错原因java.lang.IllegalA......
  • 基于Java+Neo4j开发的知识图谱+全文检索的知识库管理系统(源码分析)
    在数字化高度普及的时代,企事业机关单位在日常工作中会产生大量的文档,例如医院制度汇编,企业知识共享库等。针对这些文档性的东西,手工纸质化去管理是非常消耗工作量的,并且纸质化查阅难,易损耗,所以电子化管理显得尤为重要。【springboot+elasticsearch+neo4j+vue+activiti】实现数字......
  • (C语言)代码学习||2024.2.6||题目是codewars上的【 IP Validation】
    C语言#sscanf#代码学习#codewars题目链接:IPValidation|Codewars代码如下:#include<stdio.h>intis_valid_ip(constchar*addr){unsignedn[4],i,nc;//Mustbe4integersseparatedbydots:if(sscanf(addr,"%d.%d.%d.%d%n",&n[0],&n......
  • Java之UDP,TCP的详细解析
     练习四:文件名重复publicclassUUIDTest{publicstaticvoidmain(String[]args){Stringstr=UUID.randomUUID().toString().replace("-","");System.out.println(str);//9f15b8c356c54f55bfcb0ee3023fce8a}}```publicclassClient{public......
  • java基础语法之匿名内部类的优化格式lambda
    一:lambda表达式的概述lambda表达式实质上就是对匿内部类的优化但是又不同于匿名内部类。它的使用前提是有且仅有一个抽象方法,有一个接口。二:具体说明<1>函数式编程思想的介绍在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”在数学中,函数就是有输......
  • Java 数学运算与条件语句全解析
    JavaMathJava的Math类拥有许多方法,允许您在数字上执行数学任务。常用方法:Math.max(x,y):找到x和y的最大值Math.min(x,y):找到x和y的最小值Math.sqrt(x):返回x的平方根Math.abs(x):返回x的绝对值Math.random():返回一个介于0.0和1.0之间的随机......
  • Java 数学运算与条件语句全解析
    JavaMathJava的Math类拥有许多方法,允许您在数字上执行数学任务。常用方法:Math.max(x,y):找到x和y的最大值Math.min(x,y):找到x和y的最小值Math.sqrt(x):返回x的平方根Math.abs(x):返回x的绝对值Math.random():返回一个介于0.0和1.0之间的随......