强引用是最常用的,而虚引用在业务中几乎很难用到,下面我们举例介绍一下软引用和弱引用
先来说一下软引用的回收机制。首先设置JVM参数: -Xms20m -Xmx20m , 即只有20MB的堆空间内容。在下面代码中不断地往集合中添加House对象,而每个House有2000个Door的成员变量,狭小的堆空间加上大对象的产生,就为了尽快触达内存耗尽的临界状态。
强引用
public class SoftReferenceHouse {
public static void main(String[] args) {
List houses = new ArrayList<>();
int i =0;
while (true){
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
houses.add(new House());
System.out.println(“i==”+(++i));
}
}
}
class House{
private static final Integer DOOR_NUMBER = 2000;
public Door[] doors = new Door[DOOR_NUMBER];
class Door{}
}
上面代码会一直执行,直到报OOM,因为强引用不会释放。
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space
at com.yaspeed2.House.(SoftReferenceHouse.java:26)
at com.yaspeed2.SoftReferenceHouse.main(SoftReferenceHouse.java:17)
软引用
public class SoftReferenceHouse {
public static void main(String[] args) {
List<SoftReference> houses = new ArrayList<SoftReference>();
int i =0;
while (true){
SoftReference buyer2 = new SoftReference(new House());
houses.add(buyer2);
System.out.println(“i==”+(++i));
}
}
}
class House{
private static final Integer DOOR_NUMBER = 4000;
public Door[] doors = new Door[DOOR_NUMBER];
class Door{}
}
正常运行一段时间,内存到达耗尽的临近状态,House$Door 超过10MB左右,内存占比达到百分之七八十。
软引用的特性在数秒之后产生价值,House对象从千数量级迅速降到百数量级,内存容量迅速被释放出来。保证了程序的正常执行。
软引用SoftReference 的父类 Reference的属性: private T referent, 它指向new House()对象,而SoftReference 的get(),也是调用了super.get() 来访问父类这个私有属性。大量的House 在内存即将耗尽前,成功地一次次被清理掉。
对象buyer2虽然是引用类型,但其本身碍事占用一定内存空间的,它是被集合 ArrayList 强引用劫持的,在不断循环执行 houses.add() 后,终究会产生 OOM。
软引用、弱引用、虚引用均存在带有队列的构造方法
public SoftReference(T referent, ReferenceQueue<? super T> q) {
super(referent, q);
this.timestamp = clock;
}
可以在队列中检查哪个软引用的对象被回收了,从而把失去House 的软引用对象清理掉。
软引用一般用于在同一服务器内缓存中间结果。如果命中缓存,则提取缓存结果,否则重新计算或获取。但是,软引用肯定不是用来缓存高频数据结构的,万一服务器重启或者软引用触发大规模回收,所有的访问将直接指向数据库,导致数据库压力时大时小,甚至崩溃。
弱引用
代码如下:
public class WeakReferenceWhenIdle {
public static void main(String[] args) {
House seller = new House();
WeakReference buyer3 = new WeakReference<>(seller);
seller = null;
long start = System.nanoTime();
long count = 0;
while (true){
if(buyer3.get() == null)
{
long duration = (System.nanoTime()- start)/(1000*1000);
System.out.println("house is null and exited time = "+duration +“ms”);
break;
}else{
System.out.println(“still there.count=”+count++);
}
}
}
}
最后
金三银四到了,送上一个小福利!
break;
}else{
System.out.println(“still there.count=”+count++);
}
}
}
}
最后
金三银四到了,送上一个小福利!
[外链图片转存中…(img-TSZ961A0-1714310794722)]
[外链图片转存中…(img-g0Mw60xi-1714310794723)]
[外链图片转存中…(img-eXkRDwtx-1714310794724)]