3

使用靜態初始化實現線程安全單例時,還是實例的簡單靜態聲明就足夠了,是否需要Initialize-On-Demand成語?Initialize-On-Demand idiom vs Simpleton實現中的簡單靜態初始化程序

實例作爲靜態字段的簡單聲明:

class Singleton 
{ 
private static Singleton instance=new Singleton(); 

private Singleton() {..} 
public static Singleton getInstance() 
{ 
    return instance; 
} 
} 

VS

class Singleton { 
    static class SingletonHolder { 
     static final Singleton INSTANCE = new Singleton(); 
    } 

    private Singleton() {..} 

    public static Singleton getInstance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

我問這個是因爲布賴恩戈茨建議本文中的第一個辦法:

http://www.ibm.com/developerworks/java/library/j-dcl/index.html

而他在這篇文章中建議後者

http://www.ibm.com/developerworks/library/j-jtp03304/

是否後者的做法規定,前者沒有任何好處?

回答

3

那麼我可以說這些文章是7-9歲。

現在我們有> Java 1.5,其中我們有枚舉的力量enum。據「喬希塊」寫單,最好的辦法是寫一個單一的元素枚舉

public enum MySingleton{ 
    Singleton; 

    // rest of the implementation. 
    // .... 
} 

但對於你的問題我想有一個使用任何的實現沒有問題。我個人比較喜歡第一種選擇,因爲它直截了當,簡單易懂。

但要小心循環漏洞,我們可以通過序列化和反序列化對象或通過對對象進行克隆,在同一個JVM中同時創建這些類的更多對象。

也使類最終,因爲我們可以通過擴展類來違背單例。

+0

我不確定是否需要讓班級最終決定。擁有私人構造函數還不夠嗎? 另外,請注意,如果單例需要從類繼承,則枚舉不是一個選項。 – simpatico

3

在第一種方法中,一旦加載Singleton類,您的單身人士就會被創建。另一方面,一旦你調用getInstance()方法,它將被創建。在致電getInstance之前,Singleton班可能有很多原因需要加載。所以當你真正使用它的時候,你很可能會更早地初始化它,並且這會破壞懶惰初始化的目的。是否需要延遲初始化是一個單獨的故事。

2

當加載類Singleton時,簡單聲明模式將構造單例。當調用Singeton.getInstance()時 - 即加載類SingetonHolder時,初始化按需成語構造單例。

所以這些都是一樣的,除了時間;第二個選項允許您延遲初始化。何時選擇其中一個取決於(除其他外)你在Singleton的構造函數中做了多少工作。如果它很多,您可能會看到使用按需初始化改進的應用程序啓動時間。

這就是說,我的建議是儘量不要做太多,以便最簡單的模式適合你。

-dg