- 定義
- 特點
- 要點
- 常見問題
定義
單例模式,是一種常用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例的特殊類。通過單例模式可以保證系統中一個類只有一個實例。
特點
- 單例類只能有一個實例。
- 單例類必須自己自己創建自己的唯一實例。
- 單例類必須給所有其他對象提供這一實例。
要點
- 私有的構造方法
- 指向自己實例的私有靜態引用
- 以自己實例爲返回值的靜態的公有的方法
分類
餓漢式單例
(餓漢式單例在單例類被加載時候,就實例化一個對象交給自己的引用)
public static Singleton{
private static Singleton singleton=new Singleton();
private Singleton() { }
public static Singlenton getInstance(){
return singleton;
}
}
懶漢式單例
懶漢式在調用取得實例方法的時候纔會實例化對象。
public class Singleton{
private static Singleton singleton;
private Singleton() { }
public static Synchronized Singleton getInstance(){
if(singleton ==null){
singleton=new Singleton();
}
return singleton;
}
}
雙重鎖的形式
public class Singleton{
private static volatile Singleton instance=null;
private Singleton() { }
public static Singleton (){
if(instance==null){
synchronized(SingletonClass.class){
if(instance==null){
instance=new Singleton();
}
}
}
return instance;
}
}
常見問題
單例模式的對象長時間不用會被jvm垃圾收集器收集嗎
除非人爲地斷開單例中靜態引用到單例對象的聯接,否則jvm垃圾收集器是不會回收單例對象的。
jvm卸載類的判定條件如下:
1,該類所有的實例都已經被回收,也就是java堆中不存在該類的任何實例。
2,加載該類的ClassLoader已經被回收。
3,該類對應的java.lang.Class對象沒有任何地方被引用,無法在任何地方通過反射訪問該類的方法。
只有三個條件都滿足,jvm纔會在垃圾收集的時候卸載類。顯然,單例的類不滿足條件一,因此單例類也不會被回收。
在一個jvm中會出現多個單例嗎?
在分佈式系統、多個類加載器、以及序列化的的情況下,會產生多個單例,這一點是無庸置疑的。那麼在同一個jvm中,會不會產生單例呢?使用單例提供的getInstance()方法只能得到同一個單例,除非是使用反射方式,將會得到新的單例。
在getInstance()方法上同步有優勢還是僅同步必要的塊更優優勢?
因爲鎖定僅僅在創建實例時纔有意義,然後其他時候實例僅僅是隻讀訪問的,因此只同步必要的塊的性能更優,並且是更好的選擇。缺點:只有在第一次調用的時候,纔會出現生成2個對象,才必須要求同步。而一旦singleton 不爲null,系統依舊花費同步鎖開銷,有點得不償失。
單例類可以被繼承嗎?
根據單例實例構造的時機和方式不同,單例模式還可以分成幾種。但對於這種通過私有化構造函數,靜態方法提供實例的單例類而言,是不支持繼承的。這種模式的單例實現要求每個具體的單例類自身來維護單例實例和限制多個實例的生成。但可以採用另外一種實現單例的思路:登記式單例,來使得單例對繼承開放。