目錄
1. 餓漢式(Eager Initialization)
2. 懶漢式(Lazy Initialization)
3. 懶漢式 + 同步鎖(線程安全)
4. 雙重檢查鎖(Double-Checked Locking)
5. 靜態內部類(推薦)
6. 枚舉(最佳實踐)
單例模式的序列化與反序列化問題
單例模式適用場景
總結
單例模式是 Java 中最簡單且最常用的設計模式之一,其核心思想是確保一個類只有一個實例,并提供全局訪問點。下面分別詳解 Java 中的單例模式:
1. 餓漢式(Eager Initialization)
特點:類加載時立即創建實例,線程安全。
缺點:不支持延遲加載,可能造成資源浪費。
public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {} // 私有構造函數public static Singleton getInstance() {return INSTANCE;}
}
2. 懶漢式(Lazy Initialization)
特點:首次調用時創建實例,支持延遲加載。
缺點:多線程環境下不安全。
public class Singleton {private static Singleton INSTANCE;private Singleton() {}public static Singleton getInstance() {if (INSTANCE == null) { // 多線程可能同時進入此判斷INSTANCE = new Singleton();}return INSTANCE;}
}
3. 懶漢式 + 同步鎖(線程安全)
特點:通過synchronized
保證線程安全。
缺點:每次調用都加鎖,性能開銷大。
public class Singleton {private static Singleton INSTANCE;private Singleton() {}public static synchronized Singleton getInstance() { // 方法級同步if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;}
}
4. 雙重檢查鎖(Double-Checked Locking)
特點:線程安全且性能優化,僅首次創建時加鎖。
關鍵點:使用volatile
關鍵字禁止指令重排序。
public class Singleton {private static volatile Singleton INSTANCE; // 防止指令重排序private Singleton() {}public static Singleton getInstance() {if (INSTANCE == null) { // 第一次檢查,不加鎖synchronized (Singleton.class) {if (INSTANCE == null) { // 第二次檢查,加鎖后INSTANCE = new Singleton();}}}return INSTANCE;}
}
5. 靜態內部類(推薦)
特點:線程安全、支持延遲加載,實現簡潔。
原理:JVM 保證靜態內部類的初始化線程安全。
public class Singleton {private Singleton() {}private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}
6. 枚舉(最佳實踐)
特點:線程安全、自動支持序列化機制、防止反射攻擊。
推薦場景:需要絕對防止單例被破壞的場景。
public enum Singleton {INSTANCE;// 可以添加方法public void doSomething() {System.out.println("Singleton method called");}
}
單例模式的序列化與反序列化問題
如果單例類實現了Serializable
接口,需添加readResolve()
方法防止反序列化時創建新實例:
private Object readResolve() {return INSTANCE;
}
單例模式適用場景
- 資源管理器(如數據庫連接池、線程池)。
- 配置文件管理。
- 日志記錄器。
- GUI 中的窗口管理器。
總結
推薦使用靜態內部類或枚舉實現單例模式:
- 靜態內部類:簡潔、安全、支持延遲加載。
- 枚舉:防反射、防序列化攻擊,寫法優雅。
避免使用普通懶漢式,在多線程環境下需使用雙重檢查鎖或更優方案