首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 單例模式 4 種寫法權威對比:線程安全、懶加載、序列化、反射攻擊

     編輯:Java 相關知識

寫法一:靜態內部類 (推薦生產首選)

public class Singleton {
    private Singleton() {}
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() { return Holder.INSTANCE; }
}
  • 利用類加載機制天然線程安全;
  • 外部類加載時不初始化內部類,調用 getInstance() 才觸發初始化 → **懶加載**;
  • 無鎖、高性能、代碼簡潔。

寫法二:枚舉單例 (Effective Java 推薦)

public enum Singleton {
    INSTANCE;
    public void doSomething() { /* 业务逻辑 */ }
}
  • **天然防反射攻擊**:構造器私有,反射 newInstance() 直接拋異常;
  • **天然防序列化破壞**:JVM 保證枚舉常量單一實例;
  • 簡潔至極,但無法懶加載 (類加載即實例化)。

寫法三:雙重檢查鎖 (DCL) + volatile

public class Singleton {
    private volatile static Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {                 // 第一次檢查 (無鎖)
            synchronized (Singleton.class) {    // 鎖定
                if (instance == null) {         // 第二次檢查
                    instance = new Singleton(); // 初始化
                }
            }
        }
        return instance;
    }
}
  • volatile 關鍵:禁止指令重排序,保證其他線程見到完全初始化的對象;
  • 早期無 volatile 版本在多線程下可能返回半初始化對象;
  • 性能優於全同步,但代碼較繁瑣。

寫法四:餓漢式 (靜態常量)

public class Singleton {
    public static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
}
  • 類加載即創建,**無懶加載**;
  • 線程安全、最簡單;
  • 若實例化極其耗資源且不一定用到,不適用。

綜合對比表

維度靜態內部類枚舉DCL+volatile餓漢式
線程安全✅✅✅ (需 volatile)✅
懶加載✅❌✅❌
防反射❌✅❌❌
防序列化❌ (需 readResolve)✅❌ (需 readResolve)❌ (需 readResolve)
代碼複雜度低極低中極低

選型建議

  1. **一般業務** → 靜態內部類 (平衡懶加載、性能、簡潔);
  2. **安全敏感/框架級** → 枚舉 (防反射、防序列化破壞);
  3. **需懶加載且極度在意初始化性能** → DCL+volatile;
  4. **實例輕量、確定會用** → 餓漢式。

單例看似簡單,細節見真章。根據項目約束選擇最合適的那一款。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved