1. 程式人生 > >設計模式之單例模式實踐

設計模式之單例模式實踐

概念

單例模式即一個JVM記憶體中只存在一個類的物件例項

 

分類

1、懶漢式

類載入的時候就建立例項

2、餓漢式

使用的時候才建立例項

 

當然還有其他的生成單例的方式,雙重校驗鎖,列舉和靜態內部類,文中會有介紹

 

實踐

懶漢式

1)執行緒不安全,不可用

public class Singleton {  
    private static Singleton instance;  
    
    private Singleton (){}  

      public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  

        }  
        return instance;  
    }  

} 

2)執行緒安全,同步方法,效率低,不推薦

public class Singleton {  
    private static Singleton instance;  

    private Singleton (){}  

    public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
    }  

} 

3)執行緒不安全,會產生多個例項,不可用

public class Singleton {
    private static Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                singleton = new Singleton();
            }
        }
        return singleton;
    }
}

4) 餓漢式,無執行緒安全問題,不能延遲載入,影響系統性能

public class Singleton {  
    private static Singleton instance = new Singleton();  

    private Singleton (){}  
    public static Singleton getInstance() {  
        return instance;  
    }  

} 

5)

public class Singleton {  
    private static Singleton instance = null;  

    static {  
        instance = new Singleton();  
    }  

    private Singleton (){}  

    public static Singleton getInstance() {  
        return instance;  
    }  

}

6)雙重校驗鎖,執行緒安全,推薦使用

public class Singleton {
    private static volatile Singleton singleton;

    private Singleton() {}

    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

} 

7)靜態內部類,執行緒安全,主動呼叫時才例項化,延遲載入效率高,推薦使用

public class Singleton {  

    private static class SingletonHolder {  
        private static final Singleton INSTANCE = new Singleton();  
    }  

    private Singleton (){}  

    public static final Singleton getInstance() {  
        return SingletonHolder.INSTANCE;  
    }  

} 

8)列舉型別,無執行緒安全問題,避免反序列華建立新的例項,很少使用

public enum Singleton {  

    INSTANCE;  

    public void whateverMethod() {  

    }  

}

注意事項

1、考慮多執行緒問題

2、單例類構造方法要設定為private型別禁止外界new建立

private Singleton() {}

3、如果類可序列化,考慮反序列化生成多個例項問題,解決方案如下

private Object readResolve() throws ObjectStreamException {  
    // instead of the object we're on, return the class variable INSTANCE  
    return INSTANCE;  

}  

 

使用場景

1、工具類物件

2、系統中只能存在一個例項的類

3、建立頻繁或又耗時耗資源且又經常用到的物件

 

下面是單例模式在JDK的應用

另外,spring容器中的例項預設是單例餓漢式型別的,即容器啟動時就例項化bean到容器中,當然也可以設定懶漢式defalut-lazy-init="true"為延遲例項化,用到時再例項化。