强弱软虚引用
强引用,最普遍的情况,String s = “abc”,这个 s 就是强引用,只要强引用存在,对象就不会被垃圾回收器回收。
软引用SoftReference,用于还有用但非必须的对象,内存足够,则不会回收,内存不足,就会被回收掉
实现场景是用于内存敏感的高速缓存。软引用一般与引用队列联合使用。当软引用的对象被回收时,jvm 会将软引用加入到与之关联的引用队列中。
弱引用WeakReference,与软引用差不多,与软引用的区别是,无论内存是否足够,只要垃圾回收器线程在扫描的区域中发现了弱引用对象,直接回收掉他的内存
虚引用,也叫幻影引用。与没有引用的对象一样,不会对对象的声明周期产生影响。虚引用主要功能是,追踪对象被垃圾器回收的活动。虚引用最重要的一个特征是,虚引用必须和引用队列联合使用,当虚引用的对象被垃圾回收之前,会把虚引用加入到引用队列中。
使用场景:
1、利用软引用和弱引用解决OOM问题:用一个HashMap来保存图片的路径和相应图片对象关联的软引用之间的映射关系,在内存不足时,JVM会自动回收这些缓存图片对象所占用的空间,从而有效地避免了OOM的问题;
2、通过软引用对象重获方法实现java对象的高速缓存:比如我们创建了一个Employee类,如果每次需要查询一个雇员的信息。哪怕是几秒钟之前刚刚查询过的,都要重新构建一个实例,这是需要消耗很多时间的。我们可以通过软引用和HashMap的结合,先是保存引用方面:以软引用的方式对一个Employee对象的实例进行引用并保存该引用到HashMap上,key为此雇员的id,value为这个对象的软引用,另一方面是取出引用,缓存中是否有该Employee实例的软引用,如果有,从软引用中取得 。如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,并保存对这个新建实例的软引用;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
* @author gaoyang
* @create 2020-09-04 9:18
*/
public class 强弱软虚引用 {
public static void main(String[] args) throws Exception {
soft();
System.out.println("--------------------");
weak();
}
/**
* 软引用,用于还有用但非必须的对象,内存足够,则不会回收,内存不足,就会被回收掉。
* 实现场景是用于内存敏感的高速缓存。软引用一般与引用队列联合使用。
* 当软引用的对象被回收时,jvm 会将软引用加入到与之关联的引用队列中。
* @throws InterruptedException
*/
public static void soft() throws InterruptedException {
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue();//创建关于obj的软引用,使用引用队列
SoftReference sr = new SoftReference(obj, rq);
System.out.println(sr.get()); //get方法会输出这个obj对象的hashcode
System.out.println(rq.poll());//输出为null
obj = null;
System.gc();
Thread.sleep(2000);
//由于此时内存并没有满,所以即使 调用了gc,软引用的对象也不会被回收,
//所以rq.poll 也只会 输出null
System.out.println(sr.get()); //因为堆空间没满,可有可无的特性,所以还是会输出这个obj对象的hashcode
System.out.println(rq.poll());//队列为null
}
/**
* 具有弱引用的对象拥有的生命周期更短暂。
* 因为当JVM进行垃圾回收,一旦发现弱引用对象,无论当前内存空间是否充足,都会将弱引用回收。
* 不过由于垃圾回收器是一个优先级较低的线程,所以并不一定能迅速发现弱引用对象
* @throws Exception
*/
public static void weak() throws Exception{
Object obj = new Object();
ReferenceQueue rq = new ReferenceQueue<>();
WeakReference wr = new WeakReference(obj,rq);
System.out.println(wr.get());
System.out.println(rq.poll());
obj = null;
System.gc();
Thread.sleep(200);
//弱引用,只要gc就会被回收,所以wr会输出null,弱引用的对象也会被放进rq队列中
System.out.println(wr.get()); //这时候会输出null
System.out.println(rq.poll()); //rq队列里也会存放这个弱引用,输出它的hashcode
}
}