在JDK1.2版本之后,java对引用的概念进行了扩充,将引用分为强引用(Strongly Reference)、软引用(Soft Reference)、弱引用(Weak Reference)和虚引用。
1、强引用
强引用是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“Object obj=new Object()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象。
2、软引用
软引用是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内 存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存, 才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。
- 通常使用软引用来做缓存
public class T1 {
private List list;
private SoftReference sr;
//假设这里有个与redis连接的bean
@Bean
private RedisTemplate redis;
public List getList(){
if (sr.get() == null){
//从redis中获取
list = redis.getList();
sr = new SoftReference(list);
return list;
}else {
return (List)sr.get();
}
}
}
- 上例在实际应用中是有缺陷的,因为如果
sr.get()==null
,虽然实际的list被回收了,但sr这个对象还没有被回收,如果出现了大量这类的没回收的软引用,有可能导致内存溢出。所以软引用需要和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中,然后需要程序员手动对这些没用的软引用就行回收
public class T1 {
private List list;
private SoftReference sr;
private ReferenceQueue rfq = new ReferenceQueue();
//假设这里有个与redis连接的bean
@Bean
private RedisTemplate redis;
public List getList(){
if (sr.get() == null){
//从redis中获取
list = redis.getList();
sr = new SoftReference(list,rfq);
return list;
}else {
return (List)sr.get();
}
}
//需要另起一个线程调用此方法清除无用的软引用
public void clearCache(){
SoftReference ref = null;
while ((ref = (SoftReference)rfq.poll()) != null) {
// 清除ref
}
}
}
3、弱引用
弱引用也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只 能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只 被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。
4、虚引用
虚引用也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的 存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚 引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。在JDK 1.2版之后提供 了PhantomReference类来实现虚引用。
参考:https://www.jianshu.com/p/964fbc30151a