單例模式介紹
單例模式是java創(chuàng)建性模式的一種,提供了一種創(chuàng)建對象的最佳模式.
關(guān)于指令集亂序:
在堆中的對象,還沒有完全實例完成,就將地址交給了引用
設(shè)計意圖:
保證一個類只有一個實例,減小內(nèi)存開支,減少資源多次鏈接(當(dāng)一個類是作為資源鏈接,保證這個實例為唯一實例,而不是鏈接一次,新建一個實例,這樣能有效減少系統(tǒng)開銷).
設(shè)計思想:
1.單例類只能有一個實例.
2.單例必須自己創(chuàng)建自己的唯一實例,且構(gòu)造函數(shù)私有(反射除外).
3.單例必須給所有其他對象,提供這一個實例.
設(shè)計舉例:
android 中SharepreferenceUtils初始化.需要在application中初始化單例.
連接數(shù)據(jù)庫mysql的實例,需要一個jdbc實例.
設(shè)計方式:
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) 線程安全
這種方式采用雙鎖機(jī)制腋寨,安全且在多線程情況下能保持高性能硅瞧。
getInstance() 的性能對應(yīng)用程序很關(guān)鍵。
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.靜態(tài)內(nèi)部類
public class InnnerClassSingleton {
private InnnerClassSingleton() {
};
/**
* 靜態(tài)內(nèi)部類,其實和一個靜態(tài)外部類的內(nèi)存加載方式一樣.
* 只有在將內(nèi)部類被調(diào)用時,才會將SingleHolder.class文件,加載到方法區(qū).
* 然后將所有靜態(tài)變量(區(qū),方法)進(jìn)行初始化,達(dá)到加載完成.(懶加載效果)
* 這種方法,保證了唯一實例
* @author ccj
*
*/
private static class SingleHolder{
private final static InnnerClassSingleton INSTANCE =new InnnerClassSingleton();
}
public InnnerClassSingleton getInstance(){
return SingleHolder.INSTANCE;
}
}
6.枚舉法
1. 枚舉中的屬性必須放在最前面太惠,一般使用大寫字母表示
2. 枚舉中可以和java類一樣定義方法
3. 枚舉中的構(gòu)造方法必須是私有的
默認(rèn)枚舉實例的創(chuàng)建是線程安全的.(創(chuàng)建枚舉類的單例在JVM層面也是能保證線程安全的), 所以不需要擔(dān)心線程安全的問題
public enum EnumSingleton {
INSTANCE;
public void write(){
}
}
總結(jié)
1.惡漢模式,當(dāng)classloader加載完成.class文件后,就實例化對象,線程安全,但是沒有懶加載.在沒有明確要求懶加載時候,推薦使用.
2.懶漢模式,當(dāng)調(diào)用時才會實例化對象,但是線程不安全.即使用sychronize同步,也會出現(xiàn)指令集亂序,造成多個實例產(chǎn)生.
3.DCL雙重檢驗鎖模式,用voliate和sychronize保證只有一個實例.但是大量的校驗對比,會使效率低.
4.內(nèi)部類模式,優(yōu)雅的模式,懶加載,而且線程安全,所以推薦使用.
5.枚舉方式,最佳的單例方式,它更簡潔,自動支持序列化機(jī)制值朋,絕對防止多次實例化沮稚。推薦使用