Java單例進化史

cjsoldier發表於2016-05-27


關於單例,從我學Java到現在只知道以下兩點:

1.為了讓一個類只能有一個例項,所以使用單例的設計模式。

2.有兩種實現方法:①餓漢式 ②懶漢式


①餓漢式簡單,是執行緒安全的。但是在類載入時就建立了一個例項,但是這個單例類可能永遠不會被使用,這就造成了浪費。而且類被載入器載入時就會例項化一次。這就有可能被例項化多次。


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

    private Singleton() {
    }

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


②懶漢式 只有在呼叫getInstance方法的時候才開始例項化。 但是不是執行緒安全的,所以要在方法上加synchronized關鍵字,但是加了同步後每次只能被一個執行緒呼叫,效能大大降低。所以出來一種DCL機制。 所謂DCL就是 Double Checked Locking。 


public class DoubleCheckedLockingSingleton {
    private volatile DoubleCheckedLockingSingleton INSTANCE;

    private DoubleCheckedLockingSingleton() {
    }

    public DoubleCheckedLockingSingleton getInstance() {
        if (INSTANCE == null) {
            synchronized (DoubleCheckedLockingSingleton.class) {
                // double checking Singleton instance
                if (INSTANCE == null) {
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
        }
        return INSTANCE;
    }

    // readResolve to prevent another instance of Singleton
    private Object readResolve() {
        return INSTANCE;
    }
}


這種方法還有問題。因為new DoubleCheckedLockingSingleton();
不是原子的。

  1. 給 instance 分配記憶體
  2. 呼叫 Singleton 的建構函式來初始化成員變數
  3. 將instance物件指向分配的記憶體空間(執行完這步 instance 就為非 null 了)


所以要使用volatile關鍵字。用來防止程式碼被優化時亂序。即使這樣在Jdk1.5之前還是有問題,因為其他地方的程式碼不是volatile的。這個問題在jdk.1.5版本中修復了。

加上volatile之後還是有問題。因為反序列化時還是會建立多個例項。所以又要在單例類里加上這句防止反序列化時破壞


// readResolve to prevent another instance of Singleton
private Object readResolve() {
    return INSTANCE;
}

jdk1.5出了一個列舉型別。用列舉實現單例可謂一舉數得。程式碼簡單,完美實現單例

public enum EasySingleton {
    INSTANCE;
}

注意列舉裡
呼叫 EasySingleton.INSTANCE返回來的型別就是EasySingleton它自己。

enum
fields are compile time constants, but they are instances of their enum type. And, they`re constructed when the enum type is referenced for the first time.


以下是我參考的文章:

為什麼java中用列舉實現單例模式會更好

設計模式(二)——單例模式

Java實現單例的難點

Java高新技術2–JAVA中列舉的各種應用以及單例模式



相關文章