2015-10-12 41 views
1

我越來越困惑應該使用哪一個來創建一個同步的單例類對象。我知道以下兩種實現方式。如何使Java對象同步?哪個更好,爲什麼?

static volatile PaymentSettings paymentSettings = null; 

public static PaymentSettings getInstance() { 
    if (paymentSettings == null) { 
     synchronized (PaymentSettings.class) { 
      if (paymentSettings == null) 
       paymentSettings = new PaymentSettings(); 
     } 
    } 
    return paymentSettings; 
} 

而且

private static class PaymentSettingsInstanceHolder { 
    private static PaymentSettings instance = new PaymentSettings(); 
} 

public static PaymentSettings getInstance() { 
    return PaymentSettingsInstanceHolder.instance; 
} 

請建議我應該使用哪種方法,爲什麼?

+2

這不會使對象同步。我不確定我甚至知道這意味着什麼。這會創建一個懶惰的初始化單例!第二種方法好得多。 –

+1

通過'synchronized(PaymentSettings.class)'同步可能導致死鎖(很少,但可能),因爲鎖可從外部獲得(也就是說,如果調用者也在該鎖上同步)。如果你喜歡做同步化的惰性init,你可以使用Apache commons中的LazyInitializer。 https://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/concurrent/LazyInitializer.html - 除此之外:這兩種方法在施工時間不同(懶惰與非懶惰),而不是他們如何做同步 - 哪一個更好取決於其他方面。 –

+0

更好總是取決於你想達到的目標。你沒有在你的問題中陳述這些問題 –

回答

1

這兩種機制是實現Singleton的常見嘗試。

第一個被稱爲Double-checked locking並且通常被認爲是中斷的,儘管您對該類的鎖定技術可能是可接受的解決方法。

你的第二個是一個整潔的解決方案,但可能會在不需要時創建對象。

現在認爲最好的解決方案是使用enum。這確保該對象僅在需要時而不是在之前創建。請參閱here,瞭解爲什麼這很好。

final class Singleton { 

    private Singleton() { 
     // Make sure only I can create one. 
    } 

    private enum Single { 

     INSTANCE; 
     // The only instance - ever. 
     final Singleton s = new Singleton(); 

    } 

    public static Singleton getInstance() { 
     // Will force the construction here only. 
     return Single.INSTANCE.s; 
    } 
} 
+1

我想大多數情況是這樣匹配OP的原始簽名作爲public enum PaymentSettings {INSTANCE;他們真的需要。或者他們是這種方式的其他原因? – weston

+0

@weston - 是的,還有更多。 'enum'確保在最後一分鐘只有一次施工。它還提供了開箱即用的序列化。此外,「私人單身人士......」的存在保證**的合同只能有一個**。另外,你不應該暴露'enum'本身,你應該讓'enum'實例化單例。 – OldCurmudgeon

+0

我知道爲什麼枚舉,我問你有什麼更長的路,克服了我張貼的更短的方式(並鏈接到)。它隱藏了枚舉,但爲什麼更好?如果你按自己的方式去做,你也應該有'final'類。 – weston