餓漢式
/** * 餓漢式:開始就創建了對象,飢不擇食 */ class SingletonHungry {
private static SingletonHungry singletonHungry = new SingletonHungry();
private SingletonHungry() {
}
/** * 不存在線程安全的問題 */ public static SingletonHungry getInstance() { return singletonHungry; } } |
懶漢式
/** * 懶漢式:需要用才創建 */ class SingletonLazy {
private static SingletonLazy singletonLazy = null;
private SingletonLazy() {
} /** * 存在線程安全問題 */ public static SingletonLazy getInstance() { // public static synchronized SingletonLazy getInstance() { if(null == singletonLazy) { singletonLazy = new SingletonLazy(); } return singletonLazy; } } /** * 推薦用:靜態內部類,解決線程安全問題 * 原理: * 外部類加載時,並不需要立即加載內部類,內部類不被加載則不去初始化,所以不佔內存, * 只有當getInstance()被調用時,JVM纔會加載Inside類。 * JVM在多線程環境下初始化一個類,那麼只有有一個線程去執行這個類的方法, * 其他線程會阻塞,即同一個加載器下,一個類型只會被初始化一次,這種阻塞往往是很隱蔽的。 * 所以可以看到Inside在創建過程是線程安全的,所以說靜態內部類形式的單例可保證線程安全,也保證了單例的唯一性,同時也延遲了單例的實例化。 */ class SingletonInside {
public static class Inside { private static final SingletonInside SINGLETON_INSIDE = new SingletonInside(); }
private SingletonInside() {
}
public static SingletonInside getInstance() { return Inside.SINGLETON_INSIDE; } } /** * 雙檢查機制 */ class SingletonDoubleCheck {
private static SingletonDoubleCheck singletonDoubleCheck = null;
public static SingletonDoubleCheck getInstance() { if(null == singletonDoubleCheck) { synchronized (SingletonDoubleCheck.class) { singletonDoubleCheck = new SingletonDoubleCheck(); } } return singletonDoubleCheck; } } |