單例模式介紹
單例模式是java建立性模式的一種,提供了一種建立對象的最佳模式.
關于指令集亂序:
在堆中的對象,還沒有完全執行個體完成,就将位址交給了引用
設計意圖:
保證一個類隻有一個執行個體,減小記憶體開支,減少資源多次連結(當一個類是作為資源連結,保證這個執行個體為唯一執行個體,而不是連結一次,建立一個執行個體,這樣能有效減少系統開銷).
設計思想:
1.單例類隻能有一個執行個體.
2.單例必須自己建立自己的唯一執行個體,且構造函數私有(反射除外).
3.單例必須給所有其他對象,提供這一個執行個體.
設計舉例:
- android 中SharepreferenceUtils初始化.需要在application中初始化單例.
- 連接配接資料庫mysql的執行個體,需要一個jdbc執行個體.
設計方式:
1.餓漢式,線程安全
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}
2.懶漢式,線程不安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.懶漢式,線程安全
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
4.雙重校驗鎖(DCL,即 double-checked locking) 線程安全
這種方式采用雙鎖機制,安全且在多線程情況下能保持高性能。
getInstance() 的性能對應用程式很關鍵。
public class DCLSingleton {
private volatile static DCLSingleton instance;
private DCLSingleton(){}
public static DCLSingleton getInstance(){
if(instance==null){
synchronized (DCLSingleton.class){
if(instance==null){
instance=new DCLSingleton();
}
}
}
return instance;
}
}
5.靜态内部類
public class InnnerClassSingleton {
private InnnerClassSingleton() {
};
/**
* 靜态内部類,其實和一個靜态外部類的記憶體加載方式一樣.
* 隻有在将内部類被調用時,才會将SingleHolder.class檔案,加載到方法區.
* 然後将所有靜态變量(區,方法)進行初始化,達到加載完成.(懶加載效果)
* 這種方法,保證了唯一執行個體
* @author ccj
*
*/
private static class SingleHolder{
private final static InnnerClassSingleton INSTANCE =new InnnerClassSingleton();
}
public InnnerClassSingleton getInstance(){
return SingleHolder.INSTANCE;
}
}
6.枚舉法
1. 枚舉中的屬性必須放在最前面,一般使用大寫字母表示
2. 枚舉中可以和java類一樣定義方法
3. 枚舉中的構造方法必須是私有的
預設枚舉執行個體的建立是線程安全的.(建立枚舉類的單例在JVM層面也是能保證線程安全的), 是以不需要擔心線程安全的問題
public enum EnumSingleton {
INSTANCE;
public void write(){
}
}
總結
1.惡漢模式,當classloader加載完成.class檔案後,就執行個體化對象,線程安全,但是沒有懶加載.在沒有明确要求懶加載時候,推薦使用.
2.懶漢模式,當調用時才會執行個體化對象,但是線程不安全.即使用sychronize同步,也會出現指令集亂序,造成多個執行個體産生.
3.DCL雙重檢驗鎖模式,用voliate和sychronize保證隻有一個執行個體.但是大量的校驗對比,會使效率低.
4.内部類模式,優雅的模式,懶加載,而且線程安全,是以推薦使用.
5.枚舉方式,最佳的單例方式,它更簡潔,自動支援序列化機制,絕對防止多次執行個體化。推薦使用