每天一个面试题:四种引用,弱引用防止内存泄漏

news2024/9/22 13:36:13

每天一个面试题:四种引用

  • 四种引用基本介绍
  • 实例Demo
    • - 虚引用
    • 弱引用防止内存泄漏
    • 弱引用
  • Debug分析源码

开始全新的学习,沉淀才会有产出,一步一脚印!
面试题系列搞起来,这个专栏并非单纯的八股文,我会在技术底层的基础上,不至于Debug,还会做一些实例的实现,实现一些简单的Demo,或者用于我做过的项目中去;
代码会同步在我的gitee中去,觉得不错的同学记得一键三连求关注,感谢:
链接: Reference

四种引用基本介绍

  • 强引用就是正常的new实例,这种关系是单独一对一的,由GCroot的引用链确定,不会被GC自动回收,需要手动收回;

在这里插入图片描述

  • 软引用,是基于SoftReference确定的,类似于代理加工实现,首次gc不回收,内存不足回收
    软参考对象,由垃圾自行决定清除收集器响应内存需求。 软引用最常被用来实现内存敏感型缓存 public class SoftReference<T> extends Reference<T> {

  • 弱引用:只要gc就删除
    在这里插入图片描述

  • 虚引用:配合了一个队列进行使用,gc去将虚引用的对象及其外部资源回收掉
    在这里插入图片描述

实例Demo

- 虚引用


public class TestPhantomfegerence {



    static class MyResource extends PhantomReference<String>{

	//继承了虚引用类,构造方法中对应了 构造的 对象和队列
        public MyResource(String referent, ReferenceQueue<? super String> q) {
            super(referent, q);
        }

        public void  clean(){
            System.out.println("clean");
        }
    }

进行测试

    public static void main(String[] args) {
        ReferenceQueue<String> queue = new ReferenceQueue<>();
        List<MyResource> list = new ArrayList<>();
        list.add(new MyResource(new String("a"), queue));
        list.add(new MyResource("b", queue));
        list.add(new MyResource(new String("c"), queue));
		
		//调用系统GC
        System.gc();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Object obj;
//       gc后,如果存在资源,就打印,可以看到new的对象被打印了
        while((obj = queue.poll())!=null){
            if(obj instanceof MyResource ){
                ((MyResource) obj).clean();
            }
        }


    }

}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

弱引用防止内存泄漏

ThreadLocalMap中存在内存泄漏问题,这里可以通过一下这种方式实现


public class TestWeakReference {

    public static void main(String[] args) {
        MyweakMap map = new MyweakMap(5);
        map.put(0, new String("a"), "1");
        map.put(1, ("b"), "2");
        map.put(2, ("c"), "3");
        map.put(3, new String("d"), "3");
        System.out.println(map);
        System.gc();
        System.out.println(map.get("a"));
        System.out.println(map.get("b"));
        System.out.println(map.get("c"));
        System.out.println(map.get("d"));
        map.clean();
        System.out.println(map);
    }

    static class MyweakMap{
        static ReferenceQueue<Object> queue = new ReferenceQueue<>();
        static class Entry extends WeakReference<String> {
            String value;
			//这里的value设定,让key成为了一个弱引用,value成强引用
            public Entry(String key, String value) {
                super(key,queue);
                this.value = value;
            }

            @Override
            public String toString() {
                return "Entry{" +
                        "value='" + value + '\'' +
                        '}';
            }
        }

这里是通过判断当前的key是否为null来进行的

        public void clean(){
            Object object;
            while((object=queue.poll())!=null){
                for (int i = 0; i < table.length; i++) {
                    if(table[i]==object){
                        table[i]=null;
                    }
                }
            }
        }

如果为null,就将当前table,也就是对象Entry[]对应的单个Entry直接设置为null, static class Entry extends WeakReference<String> { 这就断开了联系
在这里插入图片描述

        public MyweakMap(int init){
            table= new Entry[init];
        }
        Entry[] table;

        public void put(int index, String key, String value){
            table[index] = new Entry(key, value);
        }

        public String get(String key){
            for(Entry entry : table){
                if(entry!=null){
                    String k = entry.get();
                    if(k!=null&&k.equals(key)){
                        return entry.value;
                    }
                }
            }
            return null;
        }


        @Override
        public String toString() {
            return "MyweakMap{" +
                    "table=" + Arrays.toString(table) +
                    '}';
        }
    }

}

在这里插入图片描述

弱引用

public class TestSoft {

    static class WeakReferenceDemo extends WeakReference<String> {
        public WeakReferenceDemo(String referent) {
            super(referent);
            System.out.println(referent);
        }


    }



    public static void main(String[] args) {

        List<WeakReference> list = new ArrayList<>();
        list.add(new TestSoft.WeakReferenceDemo(new String("a")));
        list.add(new TestSoft.WeakReferenceDemo(("b")));
        list.add(new TestSoft.WeakReferenceDemo(new String("c")));


        System.out.println(list.get(0).get());

        System.gc();

        System.out.println(list.get(0).get());


    }
}

结果展示 a b c a null

Debug分析源码

引用的底层很简单

public class WeakReference<T> extends Reference<T> {

    public WeakReference(T referent) {
        super(referent);
    }

    public WeakReference(T referent, ReferenceQueue<? super T> q) {
        super(referent, q);
    }

}

一个泛型类

public abstract class Reference<T> {

 
    private T referent;         /* Treated specially by GC */

    volatile ReferenceQueue<? super T> queue;

链表结构

    @SuppressWarnings("rawtypes")
    Reference next;


    transient private Reference<T> discovered;  /* used by VM */



    static private class Lock { };
    private static Lock lock = new Lock();



    private static Reference<Object> pending = null;

实现了一个静态内部类ReferenceHandler

  private static Lock lock = new Lock();

加载一个类锁

    private static class ReferenceHandler extends Thread {

        ReferenceHandler(ThreadGroup g, String name) {
            super(g, name);
        }

        public void run() {
            for (;;) {
                Reference<Object> r;
                synchronized (lock) {
                    if (pending != null) {
                        r = pending;
                        pending = r.discovered;
                        r.discovered = null;
                    } else {

                        try {
                            try {
                                lock.wait();
                            } catch (OutOfMemoryError x) { }
                        } catch (InterruptedException x) { }
                        continue;
                    }
                }

                // Fast path for cleaners
                if (r instanceof Cleaner) {
                    ((Cleaner)r).clean();
                    continue;
                }

                ReferenceQueue<Object> q = r.queue;
                if (q != ReferenceQueue.NULL) q.enqueue(r);
            }
        }
    }

    static {
        ThreadGroup tg = Thread.currentThread().getThreadGroup();
        for (ThreadGroup tgn = tg;
             tgn != null;
             tg = tgn, tgn = tg.getParent());
        Thread handler = new ReferenceHandler(tg, "Reference Handler");
        /* If there were a special system-only priority greater than
         * MAX_PRIORITY, it would be used here
         */
        handler.setPriority(Thread.MAX_PRIORITY);
        handler.setDaemon(true);
        handler.start();
    }


    public T get() {
        return this.referent;
    }


    public void clear() {
        this.referent = null;
    }


    public boolean enqueue() {
        return this.queue.enqueue(this);
    }


    /* -- Constructors -- */

    Reference(T referent) {
        this(referent, null);
    }

    Reference(T referent, ReferenceQueue<? super T> queue) {
        this.referent = referent;
        this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }

}

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

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

相关文章

ZStack出品|制造业专属的VMware迁移方案长啥样?

导读&#xff1a;在国家大力推动信息技术自主化的背景下&#xff0c;制造业也在积极寻找自身信息化改革的路线。作为信息化技术的基石&#xff0c;虚拟化基础架构替换迫在眉睫。本文将从技术层面详细介绍VMware迁移至 ZStack Cloud 云平台的方案&#xff0c;助力制造业实现“信…

阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

前言 有人调侃我们说&#xff1a; 程序员不如送外卖。送外卖是搬运食物&#xff0c;自己是搬运代码&#xff0c;都不产出新的东西……透支体力&#xff0c;又消耗健康&#xff0c;可替代性极强&#xff0c;30岁之后就要面临被优化的危险……想跳槽&#xff0c;但是更高的平台…

云原生|kubernetes|使用cri-docker部署基于kubeadm-1.25.4的集群

前言&#xff1a; kubernetes的部署从1.24版本开始后&#xff0c;弃用docker-shim&#xff0c;也就是说部署1.24版本后的集群不能使用docker-ce了。 比较清晰的解决方案有两个&#xff0c;一是使用containerd&#xff0c;这个是一个新的支持cri标准的shim&#xff0c;一个是使…

opencv基础-印度小哥

基础课程 第一章-读取图片、视频和摄像头 Chapter 1 – Read Images Videos and Webcams图片放在程序所在文件夹下的Resources/test.png 1.1 opencv读取一张图片并显示&#xff1a; #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include …

Jmeter命令执行生成HTML格式报告详解

1、Dashboard&#xff08;概览仪表盘&#xff09; ①、Test and Report informations Test and Report informations&#xff1a;测试和报告信息: 测试结果保存文件/测试开始时间/测试结束时间/展示过滤器。 ②、APDEX (应用性能指标) APDEX(Application Performance Index)&am…

安装pangolin问题解决|找不到makefile

前提&#xff1a; 使用的系统为ubuntu18.04版本 遇到的问题&#xff1a; 问题一&#xff1a; 按照如下命令安装时出现了错误 git clone https://github.com/stevenlovegrove/Pangolin.git cd Pangolin mkdir build cd build cmake .. make -j4 sudo make install我用的cma…

vncserver远程管理kvm虚拟机

一、安装KVM 检查服务器是否支持虚拟化&#xff08;vmx为interl平台、svm是AMD平台&#xff09;&#xff1a; grep -E -o vmx|svm /proc/cpuinfo 安装KVM所需软件包&#xff1a; yum groupinstall kvm 或者&#xff1a; yum install kvm kmod-kvm qemu kvm-qemu-img virt…

数据链路层-点对点PPP(point-to-point protocal)

点对点协议ppp是目前使用最广泛的点对点数据链路层协议 用户通过连接运营商的isp&#xff0c;用的就是pppoe协议pppoe ppp over ethernet ppp协议为点对点数据链路层协议的数据报提供了一个标准方法 封装成帧链路控制协议LCP&#xff0c;主要用于建立&#xff0c;配置&#xf…

【面试题】JSON.stringify 和fast-json-stringify有什么区别

前言 相信大家对JSON.stringify并不陌生&#xff0c;通常在很多场景下都会用到这个API&#xff0c;最常见的就是HTTP请求中的数据传输&#xff0c; 因为HTTP 协议是一个文本协议&#xff0c;传输的格式都是字符串&#xff0c;但我们在代码中常常操作的是 JSON 格式的数据&…

Flink系列之Flink中Window原理及实践

title: Flink系列 一、Flink Window 概述 官网链接&#xff1a; https://nightlies.apache.org/flink/flink-docs-release-1.14/docs/dev/datastream/operators/windows/ 摘取一段话&#xff1a; Windows are at the heart of processing infinite streams. Windows split …

基于蒙特卡洛法的规模化电动车有序充放电及负荷预测(PythonMatlab实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f389;作者研究&#xff1a;&#x1f3c5;&#x1f3c5;&#x1f3c5;主要研究方向是电力系统和智能算法、机器学…

刷爆力扣之三个数的最大乘积

刷爆力扣之三个数的最大乘积 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&#x…

运维实战100:CDH5.16.2升级至CDH6.3.2

本期来分享一个cdh企业运维实战案例 背景 为适应公司业务发展需求&#xff0c;提高相关大数据组件版本&#xff0c;解决开发中的一些技术问题和代码优化&#xff0c;需要将现有集群CDH版本由5.x版本升级为6.3.x版本&#xff0c;也是为了适配如Flink、Doris等一些计算引擎。由…

ArcGIS Pro从0到1入门实战教程 书籍淘宝线上销售,免费下载数据和视频

网址&#xff1a;https://m.tb.cn/h.USz9rbD?tkcu0Vd2cABAV 购书后五星好评&#xff0c;加下面微信&#xff0c;截图发给我们&#xff1a;送Python电子书&#xff0c;下面是我们的微信 关注翎树文化&#xff0c;获得更多好书信息 翎树文化 翎树文化致力于图书出版|科技文化|视…

leetcode:1203. 项目管理【双topo:组间topo + 组内topo】

目录题目截图题目分析ac code总结题目截图 题目分析 没有第一个条件&#xff0c;就是简单topo排序有了第一个条件&#xff0c;每个小组都需要完全隔开&#xff0c;因此不同小组间也需要一个topo排step1&#xff1a;对于group为-1的自成一组step2&#xff1a;建图&#xff0c;组…

什么是信息摘要?

信息摘要就是原数据通过某个算法生成的一个固定长度的单向Hash散列值&#xff08;PS:常用来生成信息摘要的算法有MD5与SHA算法)。固定长度得意思就是不论原文内容多大&#xff0c;其生成的信息摘要都是固定长度的。单向的意思是过程不可逆&#xff0c;即只能通过原始数据生成Ha…

Mybatis用到的设计模式

虽然我们都知道有26个设计模式&#xff0c;但是大多停留在概念层面&#xff0c;真实开发中很少遇到&#xff0c;Mybatis源码中使用了大量的设计模式&#xff0c;阅读源码并观察设计模式在其中的应用&#xff0c;能够更深入的理解设计模式。 Mybatis至少遇到了以下的设计模式的…

提高组比赛分析(1)

停更n个月&#xff0c;我又来了&#xff01; 今天打了场模拟赛&#xff0c;差点就AK IOI了 废话不多说 正片开始 题目一&#xff1a;#1751. 第 T 个数 Description 给定一个 n(0<n≤10000) 个整数构成的序列&#xff0c;每个数 a[i] 都是小于 210^9 的非负整数 &#x…

[附源码]Python计算机毕业设计SSM家居购物系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

yalmip和cplex安装步骤(Matlab)

&#x1f4cb;&#x1f4cb;&#x1f4cb;本文目录如下&#xff1a;⛳️⛳️⛳️ ​ 目录 1 yalmip和cplex的安装 1.1 yalmip安装 1.2 cplex安装过程 1 yalmip和cplex的安装 链接&#xff1a;https://pan.baidu.com/s/13One78qt1uSz92zNC6Xvlg 提取码&#xff1a;bicr --来…