2014-02-13 67 views
3

按照Josh Bloch的Effective Java Enum是實現Singleton模式的最好方法。JVM如何確保線程安全使用枚舉實現單例?

Java枚舉自己負責序列化和線程安全。但我不明白如何。

有人可以解釋嗎?我看過thisthis

第二個鏈接提供了有關枚舉能夠序列化的詳細信息,但是我沒有得到關於線程安全性的足夠解釋。

也是在枚舉中聲明的方法是線程安全的還是需要特別小心?

回答

4

static初始化塊是單線程的,使用JVM的內部鎖。即它不像其他鎖那樣出現在jstack蹤跡中。其他線程在初始化之前不能訪問任何類。所有課程都是如此,而不僅僅是enum

enum在由編譯器生成的靜態初始化塊中被初始化。

也是在枚舉中聲明的方法是線程安全的還是需要特別小心?

此外,enum就像常規類。只有您標記爲​​的方法纔會同步。注意:只需添加synchronized不會使其線程安全。 ;)

雖然enum實際上是static final實例,您可以修改它們的字段,即。枚舉中的字段默認不是final。你也可以使用反射和Unsafe.allocateInstance來修改枚舉類的內部結構。通常這不是一個好主意。

JLS 8.9.2

每個聲明枚舉與名稱爲N不變,枚舉類型的隱式聲明的E型的公共靜態最終命名爲N字段,這些字段被認爲是相同的順序聲明作爲相應的枚舉常量,在枚舉類型中顯式聲明任何靜態字段之前。

+1

請問我可以給我一個資源,它說這個「enum在編譯器生成的靜態初始化塊中初始化」。正式?我的意思是嘗試發現,但可以得到一個。 – Sam

+0

作爲一個後續問題,所有這些都可以在一個非枚舉類中完成,並使其像枚舉一樣可靠嗎? –

+0

@MisrableVariable我想是的。但是你必須付出很多努力,正如這裏所解釋的:http://java.dzone。com/articles/singleton-design-pattern-%E2%80%93 – Sam

1

枚舉是靜態實例,它們將在類加載時初始化。一旦他們初始化,你不能改變/修改它們。所以它是線程安全的。一旦創建完成,就不需要修改Enum實例。

但是,添加到枚舉類的方法不帶任何線程安全保證,除非您明確聲明它。