單例模式的 8 種寫法,整理非常全!


概念

單例模式即一個 JVM 內存中只存在一個類的對象實例。

分類

1、懶漢式

使用的時候才創建實例

2、餓漢式

類加載的時候就創建實例

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

懶漢式

1) 示例1

public class Singleton {  

    private static Singleton instance;  

    private Singleton (){}  

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

}

線程不安全,不可用。

2) 示例2

public class Singleton {  

    private static Singleton instance;  

    private Singleton (){}  

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

}

同步方法,線程安全,效率低,不推薦。

3) 示例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) 示例1

public class Singleton {  

    private static Singleton instance = new Singleton();  

    private Singleton (){}  

    public static Singleton getInstance() {  
		return instance;  
    }  

}

5) 示例2

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" 為延遲實例化,用到時再實例化。

推薦去我的博客閱讀更多:

1.Java JVM、集合、多線程、新特性系列教程

2.Spring MVC、Spring Boot、Spring Cloud 系列教程

3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程

4.Java、后端、架構、阿里巴巴等大廠最新面試題

生活很美好,明天見~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM