1. 程式人生 > >【Java】執行緒安全的單例模式----靜態內部類

【Java】執行緒安全的單例模式----靜態內部類

單例模式作為一種常見的設計模式,在程式中非常常見,主要是為了保證一個類只有一個唯一的物件。

從簡單的“餓漢式”、“懶漢式”→利用 synchronized 和 複雜的“雙重校驗DCL模式”,是一個考慮執行緒安全的過程(其實靜態的餓漢式單例模式也是執行緒安全的,後文有提到)。

後來有一篇文章上說“雙重校驗DCL模式”其實並不是執行緒安全的,我沒看懂他說的原因(原文在此),但後來發現了另一種實現執行緒安全的單例模式,靜態內部類方式,程式碼如下:

public class SingletonPattern {

    private SingletonPattern() {
    }

    private
static class SingletonPatternHolder { private static final SingletonPattern singletonPattern = new SingletonPattern(); } public static SingletonPattern getInstance() { return SingletonPatternHolder.singletonPattern; } }

剛開始我覺得這種方式挺有意思的,但是不明白為什麼要這麼寫,為此我專門請教了一位Java大神,他今天有空給我解釋了原因,我總結一下。

在這個例子中內部類 SingletonPatterHolder 的靜態變數 singletonPattern,這個變數是我們需要的那個單例,即外部類 SingletonPattern 的物件,就是那個我們需要的唯一的物件。

當我們呼叫 SingletonPattern.getInstance() 時,內部類 SingletonPatternHolder 才會初始化,靜態變數 singletonPattern 被創建出來。

這個實現思路中最主要的一點就是利用類中靜態變數的唯一性。

這種方式的優點是:
1. 不用 synchronized ,節省時間(雖然synchronized 浪費那個時間根本不算什麼時間。唉!時間就是生命,聽說不用synchronized 會快100倍,哈哈!);
2. 呼叫 getInstance() 的時候才會建立物件,不呼叫不建立,節省空間,這有點像傳說中的懶漢式。

剛開始我還有點疑惑,內部類 SingletonPatternHolder 是靜態的,那麼外部類 SingletonPattern 載入的時候,內部類 SingletonPatternHolder 會被載入,後來想起來,靜態內部類與外部類沒有什麼大的關係,外部類載入的時候,內部類不會被載入,靜態內部類只是呼叫的時候用了外部類的名字而已。

最後想了想,還是把靜態餓漢式單例模式也寫出來(執行緒安全),做個比較。

public class SingletonPattern {

    private static final SingletonPattern singletonPattern = new SingletonPattern();

    private SingletonPattern() {
    }

    public static SingletonPattern getInstance() {
        return singletonPattern;
    }
}

這個寫法也是利用類的靜態變數的唯一性,跟上面的靜態內部類有異曲同工之妙,不過這種方式有一點不足,就是類載入的時候單例物件也會跟著載入,拖延類載入速度,有時候沒用到這個類的單例物件的話,會浪費空間。有點較真哈。

《本文完》