單例模式6種實現及利弊分析


單例模式7種實現及利弊分析

單例模式三要素

  • 私有的構造方法;
  • 指向自己實例的私有靜態引用;
  • 以自己實例為返回值的靜態的公有方法

1.餓漢式

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

    private Singleton(){};
    
    public static Singleton getSingleton(){
        return singleton;
    }
}

優點:線程安全,在類加載完成時就完成了初始化,調用效率高

缺點:類加載較慢,無法達到懶加載的效果

2.懶漢式(非線程安全)

public class Singleton{
	private static Singleton singleton;
    
    private Singleton(){};
    
    public static Singleton getSingleton(){
		if(singleton == null){
            singleton = new Singleton();
        }
    	return singleton;
    }
}

優點:節約資源,實現懶加載

缺點:非線程安全,獲取對象需要實例化,調用效率低

3.懶漢式(synchronized)

public class Singleton{
	private static Singleton singleton;
    
    private Singleton(){};
    
    //	1.synchronized塊 實現線程安全
    /*public static Singleton getSingleton(){
        synchronized(Singleton.class){
        	if(singleton == null){
                singleton = new Singleton();
            }
            return singleton;
        }       
    }
    */
    
    //	2.synchronized方法 實現線程安全
    public static synchronized Singleton getSingleton(){
		if(singleton == null){
            singleton = new Singleton();
        }
    	return singleton;
    }
}

優點:線程安全,實現懶加載

缺點:獲取對象需要實例化,調用效率低

4.懶漢式(靜態內部類)

public class Singleton{
    private static class Holder{
        private static Singleton singleton = new Singleton();
    }
    
	private Singleton(){};
    
    public static Singleton getSingleton(){
        return Holder.singleton;
    }
}

優點:線程安全,實現懶加載

缺點:暫無

5.懶漢式(雙重鎖DCL)

public class Singleton{
    //volatile禁止指令重排序,避免DCL失效問題
    private static volatile Singleton singleton;
    
    private Singleton(){};
    
    public static Singleton getSingleton(){
        //避免重復的同步
        if(singleton == null){
            //如果未實例化,才進行加鎖
            synchronized(Singleton.class){
                if(singleton == null){
		      singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

優點:線程安全,實現懶加載

缺點:能被反射破解,不是絕對安全

6.懶漢式(ThreadLocal)

public class Singleton {
    private static volatile Singleton singleton;
    private static ThreadLocal<Singleton> threadLocal = new ThreadLocal<>();

    private Singleton(){};

    public static void createSingleton(){
        synchronized (Singleton.class){
            if (singleton == null){
                singleton = new Singleton();
            }
        }
        threadLocal.set(singleton);
    }

    public static Singleton getSingleton(){
        if(threadLocal.get() == null){
            createSingleton();
        }
        return singleton;
    }
}

優點:也相當於實現了雙重檢查,線程安全

缺點:效率不及傳統雙重檢查

7.枚舉類型(建議使用)

public enum  Singleton {
    INSTANCE;
    public Singleton getSingleton(){
        return INSTANCE;
    }
}

優點:安全,避免了反射攻擊,編碼簡單

缺點:無法實現懶加載,無法被繼承


免責聲明!

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



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