Java对象引用除了强引用之外还有软引用、弱引用、幻象引用以及FinalReference.
强引用:常见的普通对象引用 比如
Result counter = new Result("Johnny","12");
软引用:能豁免垃圾回收,只有在抛出OOM之前才会清理.
弱引用:不能豁免垃圾回收.用来构建没有特定约束的关系,是很多缓存实现的选择.
幻象引用:在对象被finalize之后的一种引用,不可达调用get()返回null.
FinalReference:处理native的对象,参考FinalReference详解
强弱关系:
强引用>软引用>弱引用>幻象引用
构造方式两种:
分为不带队列和带队列
Reference(T referent) {
this(referent, null);
}
Reference(T referent, ReferenceQueue<? super T> queue) {
this.referent = referent;
this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
}
通用方式:
Object obj = new Object();
ReferenceQueue refQueue = new ReferenceQueue<>();
XXXXReference<Object> p = new XXXXReference<>(counter, refQueue);
然后是调用方法
p.get()获取对象obj.
p.clear()把对象置为空.
p.isEnqueued()是否入队.
p.enqueue()是否出队
refQueue.remove(1000L)等待1秒后删除
用法示例:
SoftReference:GC后对象还在
package com.rongsoft.concurrent.phantomreference;
import lombok.extern.slf4j.Slf4j;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.concurrent.TimeUnit;
@Slf4j
public class SoftReferenceDemo {
public static void main(String[] args) {
Result counter = new Result("Johnny","12");
ReferenceQueue refQueue = new ReferenceQueue<>();
SoftReference<Object> p = new SoftReference<>(counter, refQueue);
try {
//SoftReference可达
System.out.println("SoftReference.get():"+p.get());
counter = null;
System.out.println("counter = null后:"+p.get());
System.gc();
System.out.println("System.gc()后:"+p.get());
// Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
Reference<Object> ref = refQueue.remove(1000L);
log.info("SoftReference,remove前---不为空");
TimeUnit.SECONDS.sleep(1);
if (ref != null) {
// do something
log.info("remove()后,SoftReference不为空");
}else{
log.info("remove()后,SoftReference为空");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出:
SoftReference.get():Result{name='Johnny', age='12'}
counter = null后:Result{name='Johnny', age='12'}
System.gc()后:Result{name='Johnny', age='12'}
15:17:35.979 [main] INFO com.rongsoft.concurrent.phantomreference.SoftReferenceDemo - SoftReference,remove前---不为空
15:17:36.982 [main] INFO com.rongsoft.concurrent.phantomreference.SoftReferenceDemo - remove()后,SoftReference为空
弱引用WeakReference:GC后对象不存在了
package com.rongsoft.concurrent.phantomreference;
import lombok.extern.slf4j.Slf4j;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.concurrent.TimeUnit;
@Slf4j
public class WeakReferenceDemo {
public static void main(String[] args) {
Result counter = new Result("Johnny","12");
ReferenceQueue refQueue = new ReferenceQueue<>();
WeakReference<Object> p = new WeakReference<>(counter, refQueue);
try {
System.out.println("WeakReference.get():"+p.get());
counter = null;
System.out.println("counter = null后:"+p.get());
System.gc();
System.out.println("System.gc()后:"+p.get());
// Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
Reference<Object> ref = refQueue.remove(1000L);
log.info("WeakReference,remove前---不为空");
TimeUnit.SECONDS.sleep(1);
if (ref != null) {
// do something
log.info("remove()后,WeakReference不为空");
}else{
log.info("remove()后,WeakReference为空");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果:
WeakReference.get():Result{name='Johnny', age='12'}
counter = null后:Result{name='Johnny', age='12'}
System.gc()后:null
15:29:06.431 [main] INFO com.rongsoft.concurrent.phantomreference.WeakReferenceDemo - WeakReference,remove前---不为空
15:29:07.435 [main] INFO com.rongsoft.concurrent.phantomreference.WeakReferenceDemo - remove()后,WeakReference不为空
幻象引用PhantomReference:对象一直不可达
package com.rongsoft.concurrent.phantomreference;
import lombok.extern.slf4j.Slf4j;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.concurrent.TimeUnit;
@Slf4j
public class PhantomReferenceDemo {
public static void main(String[] args) {
Result counter = new Result("Johnny","23");
ReferenceQueue refQueue = new ReferenceQueue<>();
PhantomReference<Object> p = new PhantomReference<>(counter, refQueue);
try {
//PhantomReference不可达,所以恒为空
System.out.println("PhantomReference.get():"+p.get());
counter = null;
System.out.println("counter = null后:"+p.get());
System.gc();
System.out.println("System.gc()后:"+p.get());
// Remove是一个阻塞方法,可以指定timeout,或者选择一直阻塞
Reference<Object> ref = refQueue.remove(1000L);
log.info("PhantomReference,remove前---不为空");
TimeUnit.SECONDS.sleep(1);
if (ref != null) {
// do something
log.info("remove()后,PhantomReference不为空");
}else{
log.info("remove()后,PhantomReference为空");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果:
PhantomReference.get():null
counter = null后:null
System.gc()后:null
15:38:30.992 [main] INFO com.rongsoft.concurrent.phantomreference.PhantomReferenceDemo - PhantomReference,remove前---不为空
15:38:31.995 [main] INFO com.rongsoft.concurrent.phantomreference.PhantomReferenceDemo - remove()后,PhantomReference不为空