天天看點

單例模式單例模式介紹設計方式:總結

單例模式介紹

單例模式是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.枚舉方式,最佳的單例方式,它更簡潔,自動支援序列化機制,絕對防止多次執行個體化。推薦使用