設計模式 - java程式碼實現單例模式

b9x_發表於2018-02-07

常見的單例模式的實現有五種,其中一種是餓漢式,四種是懶漢式。

  • 1.餓漢式:不存線上程安全問題。但不管使不使都會佔用記憶體空間,造成記憶體利用率降低。
package com.zx.singleton;

public class Singleton1 {

    private Singleton1(){};

    private static Singleton1 instance=new Singleton1();

    public static Singleton1 getInstance(){
        return instance;
    }

}
  • 2.懶漢式的第一種:最簡單,存線上程安全問題,不使用。
package com.zx.singleton;

public class Singleton2 {

    private Singleton2(){};

    private static Singleton2 instance;

    public static Singleton2 getInstance(){
        if(instance==null){
            instance=new Singleton2();
        }
        return instance;
    }
}
  • 3.懶漢式的第二種:解決了執行緒安全問題。其中volatile防止重排序,Sychroniezd加鎖。但存在的問題是Sychroniezd加在整個方法上導致執行效率較低。
package com.zx.singleton;

public class Singleton3 {

    private Singleton3(){};

    private static volatile Singleton3 instance;

    public static synchronized Singleton3 getInstance(){
        if(instance==null){
            instance=new Singleton3();
        }
        return instance;
    }
}
  • 4.懶漢式的第三種:不存線上程安全問題。解決了上一種的問題。存在的問題就是加鎖降低效率。
package com.zx.singleton;

public class Singleton4 {

    private Singleton4(){};

    private static volatile Singleton4 instance;

    public static Singleton4 getInstance(){
        if(instance==null){
            synchronized (Singleton4.class) {
                if(instance==null){
                    instance=new Singleton4();
                }
            }
        }
        return instance;
    }
}
  • 5.懶漢式的第四種:使用靜態內部類,解決執行緒安全問題,同時不使用鎖提高效率。
    內部類時延時載入的,也就是在第一次使用時才載入,不使用就不載入,所以可以很好的實現懶漢式單例模式。
package com.zx.singleton;

public class Singleton5 {

    private Singleton5(){};

    private static class Sub{
        private final static Singleton5 instance=new Singleton5();  
    }

    public static Singleton5 getInstance(){
        return Sub.instance;
    }
}
  • 6.列舉實現單例模式
    功能完整、使用簡潔、無償地提供了序列化機制、在面對複雜的序列化或者反射攻擊時仍然可以絕對防止多次例項化。
    列舉如何保證序列化單例:Java規範中規定,每一個列舉型別極其定義的列舉變數在JVM中都是唯一的,因此在列舉型別的序列化和反序列化上,Java做了特殊的規定。在序列化的時候Java僅僅是將列舉物件的name屬性輸出到結果中,反序列化的時候則是通過 java.lang.Enum 的 valueOf() 方法來根據名字查詢列舉物件(即通過name查詢列舉物件,並未真正對列舉物件做序列化)。

public class EnumSingleton{
    private EnumSingleton(){}
    public static EnumSingleton getInstance(){
        return Singleton.INSTANCE.getInstance();
    }
    private static enum Singleton{
        INSTANCE;
        private EnumSingleton singleton;
        //JVM會保證此方法絕對只呼叫一次
        private Singleton(){
            singleton = new EnumSingleton();
        }
        public EnumSingleton getInstance(){
            return singleton;
        }
    }
}`
  • 單例雖小,五臟俱全。

相關文章