《我要进大厂系列 七》-谈谈你对强软弱虚四种引用理解?

网友投稿 748 2022-11-22

《我要进大厂系列 七》-谈谈你对强软弱虚四种引用理解?

《我要进大厂系列 七》-谈谈你对强软弱虚四种引用理解?

文章目录

​​1.引言​​​​2.强引用​​​​3.软引用​​​​4.弱引用​​​​5.虚引用​​

1.引言

其实强引用、软引用、弱引用、虚引用这四个概念非常简单好记。

在开头先总结一下这四个引用的特点吧。

强引用:gc时不会回收软引用:只有在内存不够用时,gc才会回收弱引用:只要gc就会回收虚引用:是否回收都找不到引用的对象,仅用于管理直接内存

接下来详细看看这四种引用,结合代码,深刻的体会一下。

2.强引用

即我们平时最常见的:

Object object = new Object();

/** * 一个对象 * 重写finalize方法,可以知道已经被回收的状态 * * @author * @date 2020-05-23 */public class OneObject { @Override protected void finalize() throws Throwable { System.out.println("啊哦~OneObject被回收了"); }}/** * 强引用例子 * * @author * @date 2020-05-23 */public class ShowStrongReference { public static void main(String[] args) { // 直接new一个对象,就是强引用 OneObject oneObject = new OneObject(); System.out.println("输出对象地址:" + oneObject); System.gc(); System.out.println("第一次gc后输出对象地址:" + oneObject); oneObject = null; System.gc(); System.out.println("置为null后gc输出对象地址:" + oneObject); }}

执行代码,可以看到以下输出:

输出对象地址:com.esparks.pandora.learning.references.OneObject@72ea2f77第一次gc后输出对象地址:com.esparks.pandora.learning.references.OneObject@72ea2f77置为null后gc输出对象地址:null啊哦~OneObject被回收了

3.软引用

需要通过SoftReference对象实现:

SoftReference oneObjectSr = new SoftReference<>(new OneObject());

常用于本地缓存处理。

/** * 软引用 * 内存不够了就会回收 * 注意,运行时需要保证heap大小为35m,即小于实验中全部对象的大小,才能触发gc * -Xmx35m * * @author * @date 2020-05-23 */public class ShowSoftReference { public static void main(String[] args) { // 我们需要通过SoftReference来创建软引用 SoftReference oneObjectSr = new SoftReference<>(new OneObject()); // 我们这里创建一个大小为20m的数组 SoftReference arraySr = new SoftReference<>(new byte[1024 * 1024 * 20]); System.out.println("软引用对象oneObjectSr的地址:" + oneObjectSr); System.out.println("通过oneObjectSr关联的oneObject对象的地址:" + oneObjectSr.get()); System.out.println("数组的地址:" + arraySr.get()); System.gc(); System.out.println("正常gc一次之后,oneObject对象并没有回收。地址" + oneObjectSr.get()); // 再创建另一个大小为20m的数组,这样heap就不够大了,从而系统自动gc。如果依旧不够,会把已有的软引用关联的对象都回收掉。 System.out.println("创建另一个大小为20m的数组otherArray"); byte[] otherArray = new byte[1024 * 1024 * 20]; System.out.println("otherArray的地址:" + otherArray); // gc后,软引用对象还在,但是通过软引用对象创建的对象就被回收了 System.out.println("现在srObject的地址:" + arraySr); System.out.println("现在srObject中oneObject对象的地址:" + arraySr.get()); System.out.println("刚才的数组对象也被回收啦,地址:" + arraySr.get()); }}

执行代码,可以看到以下输出:

软引用对象oneObjectSr的地址:java.lang.ref.SoftReference@72ea2f77通过oneObjectSr关联的oneObject对象的地址:com.esparks.pandora.learning.references.OneObject@33c7353a数组的地址:[B@681a9515正常gc一次之后,oneObject对象并没有回收。地址com.esparks.pandora.learning.references.OneObject@33c7353a创建另一个大小为20m的数组otherArray啊哦~OneObject被回收了otherArray的地址:[B@3af49f1c现在srObject的地址:java.lang.ref.SoftReference@19469ea2现在srObject中oneObject对象的地址:null刚才的数组对象也被回收啦,地址:null

4.弱引用

需要通过WeakReference对象实现:

WeakReference oneObjectWr = new WeakReference<>(new OneObject());

常用于Threadlocal。

/** * 弱引用 * 只要gc就会回收 * * @author * @date 2020-05-23 */public class ShowWeakReference { public static void main(String[] args) { // 我们需要通过WeakReference来创建弱引用 WeakReference objectWr = new WeakReference<>(new OneObject()); System.out.println("弱引用objectWr的地址:" + objectWr); System.out.println("弱引用objectWr关联的oneObject对象的地址:" + objectWr.get()); System.gc(); // gc后,弱引用对象还在,但是通过弱引用对象创建的对象就被回收了 System.out.println("gc后,弱引用objectWr的地址:" + objectWr); System.out.println("gc后,弱引用objectWr关联的oneObject对象的地址:" + objectWr.get()); }}

5.虚引用

需要通过PhantomReference对象和ReferenceQueue实现:

private ReferenceQueue queue = new ReferenceQueue<>();PhantomReference oneObjectPr = new PhantomReference<>(new OneObject(), queue);

无论是否gc,其实都获取不到通过PhantomReference创建的对象。

其仅用于管理直接内存,起到通知的作用。

/** * 虚引用 * 只用于管理直接内存,起到通知的作用 * * @author * @date 2020-05-23 */public class ShowPhantomReference { /** * 虚引用需要的队列 */ private static final ReferenceQueue QUEUE = new ReferenceQueue<>(); public static void main(String[] args) { // 我们需要通过WeakReference来创建虚引用 PhantomReference objectPr = new PhantomReference<>(new OneObject(), QUEUE); System.out.println("虚引用objectPr的地址:" + objectPr); System.out.println("虚引用objectPr关联的oneObject对象的地址:" + objectPr.get()); // 触发gc,然后检查队列中是否有虚引用 while (true) { System.gc(); Reference poll = QUEUE.poll(); if (poll != null) { System.out.println("队列里找到objectPr啦" + poll); break; } } }}

执行代码,可以看到以下输出:

虚引用objectPr的地址:java.lang.ref.PhantomReference@72ea2f77虚引用objectPr关联的oneObject对象的地址:null啊哦~OneObject被回收了队列里找到objectPr啦java.lang.ref.PhantomReference@72ea2f77

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:电商项目专题(一)-电商入门
下一篇:JDBC专题(一)-JDBC入门
相关文章

 发表评论

暂时没有评论,来抢沙发吧~