引用這個概念經常被提及,今天總結一下。
強引用
強引用即(StrongReference)我們最常使用的引用,A a=new A()。這個a就是一個強引用。
軟引用
即(SoftReference),
Object obj = new Object();
SoftReference<Object> sf = new SoftReference<Object>(obj);
obj = null;
sf.get();//有時候會返回null
弱引用
即(WeakReference)
Object obj = new Object();
WeakReference<Object> wf = new WeakReference<Object>(obj);
obj = null;
wf.get();//有時候會返回null
wf.isEnQueued();//返回是否被垃圾回收器標記爲即將回收的垃圾
虛引用
即(PhantomReference)
Object obj = new Object();
PhantomReference<Object> pf = new PhantomReference<Object>(obj);
obj=null;
pf.get();//永遠返回null
pf.isEnQueued();//返回是否從內存中已經刪除
引用的作用
強引用就不說了,大家都知道。軟引用一般可以用來做緩存,比如一個很大的對象,我們重新加載比較耗時間,用強引用又可能內存溢出,就用軟引用咯。
弱引用的典型引用就是WeakHashMap,有時候我們想要JVM快速回收某個對象時,就用弱引用。
下面來個例子:
package weakmap;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
public class ThreadGC implements Runnable {
private WeakReference<byte[]> k;
private ReferenceQueue referenceQueue;
public void setReferenceQueue(ReferenceQueue referenceQueue) {
this.referenceQueue=referenceQueue;
}
@Override
public void run() {
// TODO Auto-generated method stub
int cnt = 0;
try {
while((k = (WeakReference) referenceQueue.remove()) != null) {
System.out.println((cnt++) + "回收了:" + k);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package weakmap;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Object value = new Object();
Map<Object, Object> map = new HashMap<>();
ReferenceQueue referenceQueue=new ReferenceQueue<>();
ThreadGC threadGC=new ThreadGC();
threadGC.setReferenceQueue(referenceQueue);
new Thread(threadGC).start();
for(int i = 0;i < 10000;i++) {
byte[] bytes = new byte[1024*1024];
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(bytes, referenceQueue);
map.put(weakReference, value);
}
System.out.println("map.size->" + map.size());
}
}
WeakHashMap應該也是類似的實現,把HashMap的key用弱引用,可以實現快速內存回收。
虛引用:
下面來個例子:
package weakmap;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;
public class Test {
public static boolean isRun = true;
@SuppressWarnings("static-access")
public static void main(String[] args) throws Exception {
String abc = new String("abc");
System.out.println(abc.getClass() + "@" + abc.hashCode());
final ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
new Thread() {
public void run() {
while (isRun) {
Object obj = referenceQueue.poll(); //引用隊列裏有對象
if (obj != null) {
try {
Field rereferent = Reference.class
.getDeclaredField("referent");
rereferent.setAccessible(true);
Object result = rereferent.get(obj);
System.out.println("gc will collect:"
+ result.getClass() + "@"
+ result.hashCode() + "\t"
+ (String) result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}.start();
PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,
referenceQueue);
abc = null;
Thread.currentThread().sleep(3000);
System.gc();
Thread.currentThread().sleep(3000);
isRun = false;
}
}