关于Java中的WeakReference有哪些知识点?
来源:简书 发布时间:2020-05-21 13:37:37

一. 简介

在看ThreadLocal源码的时候,其中嵌套类ThreadLocalMap中的Entry继承了WeakReferenc,为了能搞清楚ThreadLocal,只能先了解下了WeakReferenc(是的,很多时候为了搞清楚一个东西,不得不往上追好几层,先搞清楚其所依赖的东西。)

下面进入正题,WeakReference如字面意思,弱引用, 当一个对象仅仅被weak reference(弱引用)指向, 而没有任何其他strong reference(强引用)指向的时候, 如果这时GC运行, 那么这个对象就会被回收,不论当前的内存空间是否足够,这个对象都会被回收。

二. 认识WeakReference类

WeakReference继承Reference,其中只有两个构造函数:

undefined

public class WeakReference extends Reference {

public WeakReference(T referent) {

super(referent);

}

public WeakReference(T referent, ReferenceQueueq) {

super(referent, q);

}

}

WeakReference(T referent):referent就是被弱引用的对象(注意区分弱引用对象和被弱引用的对应,弱引用对象是指WeakReference的实例或者其子类的实例),比如有一个Apple实例apple,可以如下使用,并且通过get()方法来获取apple引用。也可以再创建一个继承WeakReference的类来对Apple进行弱引用,下面就会使用这种方式。

undefined

WeakReference appleWeakReference = new WeakReference<>(apple);

Apple apple2 = appleWeakReference.get();

WeakReference(T referent, ReferenceQueueq):与上面的构造方法比较,多了个ReferenceQueue,在对象被回收后,会把弱引用对象,也就是WeakReference对象或者其子类的对象,放入队列ReferenceQueue中,注意不是被弱引用的对象,被弱引用的对象已经被回收了。

三. 使用WeakReference

下面是使用继承WeakReference的方式来使用软引用,并且不使用ReferenceQueue。

简单类Apple

undefined

package io.github.brightloong.lab.reference;

/**

* Apple class

*

* @author BrightLoong

* @date 2018/5/25

*/

public class Apple {

private String name;

public Apple(String name) {

this.name = name;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

/**

* 覆盖finalize,在回收的时候会执行。

* @throws Throwable

*/

@Override

protected void finalize() throws Throwable {

super.finalize();

System.out.println("Apple: " + name + " finalize。");

}

@Override

public String toString() {

return "Apple{" +

"name='" + name + '\'' +

'}' + ", hashCode:" + this.hashCode();

}

}

继承WeakReference的Salad

undefined

package io.github.brightloong.lab.reference;

import java.lang.ref.WeakReference;

/**

* Salad class

* 继承WeakReference,将Apple作为弱引用。

* 注意到时候回收的是Apple,而不是Salad

*

* @author BrightLoong

* @date 2018/5/25

*/

public class Salad extends WeakReference {

public Salad(Apple apple) {

super(apple);

}

}

Clent调用和输出

undefined

package io.github.brightloong.lab.reference;

import java.lang.ref.WeakReference;

/**

* Main class

*

* @author BrightLoong

* @date 2018/5/24

*/

public class Client {

public static void main(String[] args) {

Salad salad = new Salad(new Apple("红富士"));

//通过WeakReference的get()方法获取Apple

System.out.println("Apple:" + salad.get());

System.gc();

try {

//休眠一下,在运行的时候加上虚拟机参数-XX:+PrintGCDetails,输出gc信息,确定gc发生了。

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

//如果为空,代表被回收了

if (salad.get() == null) {

System.out.println("clear Apple。");

}

}

}

输出如下:

undefined

Apple:Apple{name='红富士'}, hashCode:1846274136

[GC (System.gc()) [PSYoungGen: 3328K->496K(38400K)] 3328K->504K(125952K), 0.0035102 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

[Full GC (System.gc()) [PSYoungGen: 496K->0K(38400K)] [ParOldGen: 8K->359K(87552K)] 504K->359K(125952K), [Metaspace: 2877K->2877K(1056768K)], 0.0067965 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

Apple: 红富士 finalize。

clear Apple。

ReferenceQueue的使用

undefined

package io.github.brightloong.lab.reference;

import java.lang.ref.Reference;

import java.lang.ref.ReferenceQueue;

import java.lang.ref.WeakReference;

/**

* Client2 class

*

* @author BrightLoong

* @date 2018/5/27

*/

public class Client2 {

public static void main(String[] args) {

ReferenceQueue appleReferenceQueue = new ReferenceQueue<>();

WeakReference appleWeakReference = new WeakReference(new Apple("青苹果"), appleReferenceQueue);

WeakReference appleWeakReference2 = new WeakReference(new Apple("毒苹果"), appleReferenceQueue);

System.out.println("=====gc调用前=====");

Referencereference = null;

while ((reference = appleReferenceQueue.poll()) != null ) {

//不会输出,因为没有回收被弱引用的对象,并不会加入队列中

System.out.println(reference);

}

System.out.println(appleWeakReference);

System.out.println(appleWeakReference2);

System.out.println(appleWeakReference.get());

System.out.println(appleWeakReference2.get());

System.out.println("=====调用gc=====");

System.gc();

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("=====gc调用后=====");

//下面两个输出为null,表示对象被回收了

System.out.println(appleWeakReference.get());

System.out.println(appleWeakReference2.get());

//输出结果,并且就是上面的appleWeakReference、appleWeakReference2,再次证明对象被回收了

Referencereference2 = null;

while ((reference2 = appleReferenceQueue.poll()) != null ) {

//如果使用继承的方式就可以包含其他信息了

System.out.println("appleReferenceQueue中:" + reference2);

}

}

}

结果输出如下:

undefined

=====gc调用前=====

java.lang.ref.WeakReference@6e0be858

java.lang.ref.WeakReference@61bbe9ba

Apple{name='青苹果'}, hashCode:1627674070

Apple{name='毒苹果'}, hashCode:1360875712

=====调用gc=====

Apple: 毒苹果 finalize。

Apple: 青苹果 finalize。

=====gc调用后=====

null

null

appleReferenceQueue中:java.lang.ref.WeakReference@6e0be858

appleReferenceQueue中:java.lang.ref.WeakReference@61bbe9ba

Process finished with exit code 0

可以看到在队列中(ReferenceQueue),调用gc之前是没有内容的,调用gc之后,对象被回收了,并且弱引用对象appleWeakReference和appleWeakReference2被放入了队列中。

作者:BrightLoong

标签: weakreference

猜你喜欢

海伦司(09869.HK)宣布消息:拟2.23亿元收购武汉办

海伦司(09869 HK)宣布,于2022年1月28日,公司全资附属公司武汉餐饮与长江产业园订立物业收购协议...更多

2022-01-29 14:29:09

圣济堂(600227.SH)公布消息:2021年预亏4500万到6500万元

圣济堂(600227 SH)公布,公司2021年业绩预计亏损4500万元到6500万元;扣除非经常性损益事项后,公司...更多

2022-01-29 14:29:09

*ST海医(600896.SH)公布2021年年度业绩预亏公告

*ST海医(600896 SH)公布2021年年度业绩预亏公告,预计公司2021年营业收入为1 1亿元至1 2亿元,扣...更多

2022-01-29 14:29:09

易纬集团(03893.HK)公布消息:预计中期综合净亏损

易纬集团(03893 HK)公布,与截至2020年12月31日止六个月的综合净亏损约380万港元比较,集团预期于...更多

2022-01-28 14:52:04

密尔克卫公布消息:实控人李仁莉拟以大宗交易减持

密尔克卫(603713 SH)公布,截止公告披露日,公司实际控制人、股东李仁莉持有公司股份2238 1009万...更多

2022-01-28 14:52:04

龙佰集团公布消息:首次公开发行境外上市外资股(H

龙佰集团(002601 SZ)公布,公司于2022年1月27日收到中国证券监督管理委员会出具的《关于核准龙佰集...更多

2022-01-28 14:06:37

英飞拓(002528.SZ)披露2021年度业绩预告 预亏9亿

英飞拓(002528 SZ)披露2021年度业绩预告,预计2021年度实现归属于上市公司股东的净利润为亏损9 00...更多

2022-01-27 16:22:58

新宏泽(002836.SZ)公布2021年度业绩预告 净利润

新宏泽(002836 SZ)公布2021年度业绩预告,公司预计实现2021年归属于上市公司股东的净利润为963 93...更多

2022-01-26 14:11:37

中恒集团(600252.SH):2021年度净利预减30%-50%

中恒集团(600252 SH)公布2021年年度业绩预减公告,公司2021年度实现归属于上市公司股东的净利润与...更多

2022-01-26 14:11:37

迪森股份(300335.SZ)公布消息:2021年度预亏6000

迪森股份(300335 SZ)公布,预计2021年度归属于上市公司股东的净亏损6000万元至9000万元,上年同期...更多

2022-01-26 14:11:37