1、Java中有哪幾種引用?它們的含義和區別是什么?
(1)強引用(StrongReference)
強引用就是指在程序代碼之中普遍存在的,類似"Object obj = new Object()" 這類的引
用只要強引用還存在,垃圾收集器永遠不會回收掉被應用的對象。如果想中斷強引用
和某個對象之間的關系,可以將引用賦值為null.
(2)軟引用(SoftReference)
軟引用使用來描述一些還有用但并非必需的對象,對于軟引用關聯著的對象,在系統將
要發生內存溢出異常之前,將會把這些對象列進回收范圍之中進行第二次回收。如果這
次回收還沒有足夠的內存,才會拋出內存溢出異常。
String str = new String("abc"); // 強引用
SoftReference<String> softRef=new SoftReference<String>(str); // 軟引用
當內存不足時,等價于:
If(JVM.內存不足()) {
str = null; // 轉換為軟引用
System.gc(); ``// 垃圾回收器進行回收`
}
(3)弱引用(WeakReference)
弱引用也是用來描述非必須對象的,它的強度比軟引用要弱一些,被弱引用關聯的對象
只能生存到下一次垃圾收集發生之前。當垃圾收集器工作時,無論當前內存是否足夠,
都會回收掉只被弱引用關聯的對象。
String str=new String("abc");
WeakReference<String> abcWeakRef = new WeakReference<String>(str);
str=null;
當垃圾回收器進行掃描回收時等價于:
str = null;
System.gc();
(4)虛引用(PhantomReference)
“虛引用”顧名思義,就是形同虛設,與其他幾種引用都不同,虛引用并不會決定對象
的生命周期。如果一個對象僅持有虛引用,那么它就和沒有任何引用一樣,在任何時
候都可能被垃圾回收器回收。
虛引用主要用來跟蹤對象被垃圾回收器回收的活動。虛引用與軟引用和弱引用的一個
區別在于:虛引用必須和引用隊列 (ReferenceQueue)聯合使用。當垃圾回收器準
備回收一個對象時,如果發現它還有虛引用,就會在回收對象的內存之前,把這個虛
引用加入到與之 關聯的引用隊列中。
2、請用Java實現一個線程安全且高效的單例模式。
(1)利用了類加載機制來保證只創建一個instance實例,只要應用中不使用內部類,JVM就不會去加載這個單例類,也就不會創建單例對象,從而實現懶漢式的延遲加載。也就是說這種方式可以同時保證延遲加載和線程安全。
但是有二點不安全 :
(1)可能會有人使用反射強行調用我們的私有構造器
(2)都需要額外的工作(Serializable、transient、readResolve())來實現序列化,否則每次反序列化一個序列化的對象實例時都會創建一個新的實例。
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
/**
* 靜態內部類
*/
private static class SingletonHolder {
private static final Singleton sInstance = new Singleton();
}
}
(2)使用DCL, 保證序列化與反序列化安全,延遲加載,線程安全,防反射
public class MySingleton implements Serializable {
private static final long serialVersionUID = 5852078463222747168L;
private static volatile MySingleton singleton;
private static boolean isFirst = true;
private MySingleton() {
if (isFirst) {
isFirst = false;
} else {
throw new RuntimeException("破壞了單列,第二個實列創建失敗");
}
}
public static MySingleton getInstance() {
if (singleton == null) {
synchronized (MySingleton.class) {
if (singleton == null) {
singleton = new MySingleton();
}
}
}
return singleton;
}
//序列化安全
private Object readResolve() {
return singleton;
}
}