天天看點

java實作單例模式的四種方式

1.餓漢模式

public class Singleton1 {

    private static Singleton1 instance = new Singleton1();

    private Singleton1() {
    }

    public static Singleton1 getInstance() {
        return instance;
    }

    /**
     * 餓漢模式,線程安全,但是不能延時加載,如果資源不被調用,那麼就會浪費
     */
}
           

2.懶漢式

public class Singleton2 {

    private static Singleton2 instance;

    private Singleton2() {
    }

    public static Singleton2 getInstance() {
        if (instance != null) {
            instance = new Singleton2();
        }
        return instance;
    }
    /**
     * 懶漢式,線程安全,可以延時加載,但是不能解決編譯器優化導緻的執行個體未初始化問題
     */
}

           

3.雙重鎖判斷

public class Singleton3 {

    private static Singleton3 instance;

    private Singleton3() {
    }

    public static Singleton3 getInstance() {
        if (instance != null) {
            synchronized (Singleton3.class) {
                if (instance != null) {
                    instance = new Singleton3();
                }
            }
        }
        return instance;
    }
    /**
     * 雙重鎖判斷,JVM優化導緻new操作的三個步驟(如下所示)可能會亂序,
     * 進而在并發場景下拿到未初始化的執行個體
     * 
     *  1.配置設定一塊記憶體M
     *  2.在M上初始化Singleton3對象
     *  3.将M的位址估值給instance變量
     *
     *  JVM可能會讓2和3交換順序,這樣就導緻了未初始化
     */
}
           

4.靜态内部類

public class Singleton4 {

    private Singleton4() {
    }

    private static class Singleton4InstanceClass {
        private static final Singleton4 instance = new Singleton4();
    }

    public static Singleton4 getInstance() {
        return Singleton4InstanceClass.instance;
    }
    /**
     * 采用靜态内部類的形式就相當于是餓漢模式的改進,将不能延時加載的缺點處理掉了,
     * 是以該模式線程安全,調用效率高,可以延時加載
     */
}
           

5.使用

  • 單例對象 占用資源少,不需要延時加載,餓漢
  • 單例對象 占用資源多,需要延時加載,靜态内部類 好于 懶漢式

繼續閱讀