2012-12-05 119 views
9

我有兩個選擇:單和公共靜態變量的Java

  1. Singleton模式

    class Singleton{ 
        private static Singleton singleton = null; 
    
        public static synchronized Singleton getInstance(){ 
         if(singleton == null){ 
          singleton = new Singleton(); 
         } 
         return singleton; 
        } 
    } 
    
  2. 使用static final

    private static final Singleton singleton = new Singleton(); 
    
    public static Singleton getSingleton() { 
        return singleton; 
    } 
    

請告訴我有什麼區別? (單線程或多線程)

更新:我知道Bill Pugh或enum方法。 我不是在尋找正確的方法,但我只使用了1.是否真的有什麼區別b/w 1或2?

+0

更新後的問題沒有什麼區別。 –

+1

這個問題與單身無關。您詢問有關從同步/非同步上下文訪問靜態字段的問題。請編輯標籤。 – Juvanis

+0

@BhavikAmbani我不同意,因爲第一個選項會鎖定試圖獲取實例的每個線程,因此性能稍差。 –

回答

10

主要區別在於,對於第一個選項,只有在調用getInstance時纔會初始化singleton,而使用第二個選項時,只要載入包含的類,它就會初始化。

第三(優選的)選項,這是懶和線程安全是使用一個枚舉:

public enum Singleton { 
    INSTANCE; 
} 
+0

我的錯誤,不知何故錯過了它。已經更新了現在的問題。另外,我意識到ENUM單例實例,只是想知道b.w 2的區別,但是非常感謝! – Achow

2

有一點不同:

解決方案1是一個延遲初始化,單個實例將是在getInstance

解決方案2的第一次調用創建是一個渴望初始化,單個實例將被創建時,類loades

他們都是線程安全的,調用第二個多線程是有點誤導

+1

那麼,我沒有把多線程位。它被編輯..:P – Achow

1

因此,隨着更新上述兩個選項是線程安全的。但​​選項要求每個調用instance的線程獲取此鎖,從而降低性能,如果這樣做很多。此外,在方法級別使用​​可能會存在使用公共可用鎖(該類本身)的潛在問題,因此如果某個線程獲取了此鎖(可能),最終可能會導致死鎖。 static final選項更高性能,但不會對單例進行惰性初始化(根據系統情況,這可能不是問題)。

,允許線程安全延遲初始化單例的另一種選擇是如下:

public class MySingleton{ 
     private static class Builder{ 
      private static final MySingleton instance = new MySingleton(); 
     } 

     public static MySingleton instance(){ 
      return Builder.intance; 
     } 
} 

此操作,因爲執行包含類的任何方法之前靜態內部類保證的廣告被初始化。

+0

-1選民,照顧澄清推理? –

+0

我剛剛重讀了答案,它沒有我認爲的問題。對不起這個。 :)刪除我的-1。答案看起來有點像詞沙拉給我,雖然...只是幾乎觸及真正的差異(懶惰與渴望的初始化)。你提到性能和鎖定,但這些並不是主要區別。 – cHao

-1

Java中的單例實現(如果您真的想這樣做)可以以比您爲急切和懶惰初始化描述的更優雅的方式執行。分別由Joshua Bloch描述的the enum way和由Bill Pugh提出的the SingletonHolder solution

維基百科的文章也是理解模式的好開始,並且回答你的問題。

+1

不回答問題。如果你想提出一個更好的方法,那沒問題......但至少在你這樣做的時候回答被問到的問題。 – cHao

+0

是啊,你是對的... –

2

第一個解決方案似乎更懶,但實際上並不是。

第一次訪問靜態方法/字段時會初始化一個類。

很可能getInstance()是該類中唯一可公開訪問的靜態方法/字段。這是單身人士的觀點。

然後,當有人第一次撥打getInstance()時,這個班級被初始化。這意味着兩種解決方案在懶惰方面基本相同。

當然,第二種解決方案看起來更好,性能更好。

+0

懶惰的存在,直到getInstance()被顯式調用時才創建Singleton的實例。這個類顯然會被加載兩次。或者我錯過了什麼?在第二種解決方案中爲 – Achow

+1

,實例僅在類初始化時創建;只有在訪問靜態方法/字段時,即調用getInstance()時,纔會初始化類。 – irreputable