目錄 單例模式 1.餓漢式(線程安全) 2.懶漢式(通過synchronized修飾獲取實例的方法保證線程安全) 3.雙重校驗鎖的方式實現單例模式 4.靜態內部類方式實現單例模式【推薦】
單例模式
1.餓漢式(線程安全)
package 并發的例子. 單例模式;
public class Singleton1 { private static final Singleton1 INSTANCE = new Singleton1 ( ) ; private Singleton1 ( ) { } public static Singleton1 getInstance ( ) { return INSTANCE ; } public static void main ( String [ ] args) { Singleton1 instance1 = Singleton1 . getInstance ( ) ; Singleton1 instance2 = Singleton1 . getInstance ( ) ; Singleton1 instance3 = Singleton1 . getInstance ( ) ; System . out. println ( instance1 == instance2) ; System . out. println ( instance2 == instance3) ; System . out. println ( instance1 == instance3) ; }
}
2.懶漢式(通過synchronized修飾獲取實例的方法保證線程安全)
package 并發的例子. 單例模式;
public class Singleton2 { private static Singleton2 instance; private Singleton2 ( ) { } public static synchronized Singleton2 getInstance ( ) { if ( instance == null ) { instance = new Singleton2 ( ) ; } return instance; } public static void main ( String [ ] args) { Singleton2 s1 = Singleton2 . getInstance ( ) ; Singleton2 s2 = Singleton2 . getInstance ( ) ; Singleton2 s3 = Singleton2 . getInstance ( ) ; System . out. println ( s1. hashCode ( ) ) ; System . out. println ( s2. hashCode ( ) ) ; System . out. println ( s3. hashCode ( ) ) ; }
}
3.雙重校驗鎖的方式實現單例模式
package 并發的例子. 單例模式;
public class Singleton3 { private static volatile Singleton3 instance; private Singleton3 ( ) { } public static Singleton3 getInstance ( ) { if ( instance == null ) { synchronized ( Singleton3 . class ) { if ( instance == null ) { instance = new Singleton3 ( ) ; } } } return instance; }
}
4.靜態內部類方式實現單例模式【推薦】
package 并發的例子. 單例模式;
public class Singleton4 { private Singleton4 ( ) { } private static class SingletonHolder { private static final Singleton4 INSTANCE = new Singleton4 ( ) ; } public static Singleton4 getInstance ( ) { return SingletonHolder . INSTANCE ; } public static void main ( String [ ] args) { Singleton4 s1 = Singleton4 . getInstance ( ) ; Singleton4 s2 = Singleton4 . getInstance ( ) ; Singleton4 s3 = Singleton4 . getInstance ( ) ; System . out. println ( s1. hashCode ( ) ) ; System . out. println ( s2. hashCode ( ) ) ; System . out. println ( s3. hashCode ( ) ) ; }
}
1. 為什么用靜態內部類?
靜態內部類 SingletonHolder 是 “懶漢”:外部類 Singleton4 加載時,它不會跟著加載,真正調用 getInstance ( ) 時才會加載,實現 “用的時候再創建”(懶加載)。
2. 線程安全怎么保證?
JVM 加載類時,會保證 “同一類全局只加載一次”,且加載過程是線程安全的(多線程同時調用 getInstance ( ) ,SingletonHolder 也只會加載一次)。
因此 INSTANCE 只會創建一次,天然線程安全。
3. 對比其他單例的優勢
比 “餓漢式” 懶:餓漢式類加載時就創建實例,靜態內部類做到了 “用的時候才創建”。
比 “懶漢式(同步方法)” 高效:無需手動加鎖,依托 JVM 類加載機制保證線程安全,性能更好。
4. 適合場景
需要 懶加載(延遲初始化),且希望 線程安全、代碼簡潔 的場景。
推薦作為日常開發中 “單例模式” 的首選方案,兼顧性能和安全性。