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

Java 設計模式之單例模式介紹

     編輯:Java 相關知識

單例模式:確保類只有一個實例,並提供全局訪問點

單例模式 屬於創建型模式。它確保某個類在 JVM 中只有一個實例存在,並提供一個全局訪問點 getInstance()。常用於資源管理器、線程池、緩存、配置類、數據庫連接池等場景。

常見實現方式

1. 餓漢式(類加載時創建,線程安全)

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {} // 私有構造器
    public static Singleton getInstance() { return INSTANCE; }
}

優點:實現簡單,無線程安全問題。
缺點:類加載即創建,若實例從未使用則浪費內存;無法處理構造器拋異常的情況。

2. 懶漢式(雙重檢查鎖 DCL,JDK 1.5+ 安全)

public class Singleton {
    private volatile static Singleton instance; // volatile 禁止指令重排
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) { // 第一次檢查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次檢查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

優點:延遲加載,高併發下性能較好。
注意:volatile 關鍵字至關重要,防止指令重排導致其他線程看到半初始化對象。

3. 靜態內部類(推薦:延遲加載 + 線程安全 + 簡潔)

public class Singleton {
    private Singleton() {}
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() { return Holder.INSTANCE; }
}

利用類加載機制保證線程安全,只有調用 getInstance() 時才會加載 Holder 類並創建實例。

4. 枚舉單例(Effective Java 推薦:防反射、防序列化破壞)

public enum Singleton {
    INSTANCE;
    public void doSomething() { ... }
}
// 調用:Singleton.INSTANCE.doSomething();

注意事項與陷阱

  • 反射攻擊:除枚舉外,其他方式均可通過反射調用私有構造器創建新實例。可在構造器中檢查 if (INSTANCE != null) throw ... 防禦。
  • 序列化破壞:實現 Serializable 時需聲明 readResolve() 返回同一實例。
  • 多類加載器環境:Tomcat、OSGi、EJB 等多 ClassLoader 環境下,每個加載器可能創建各自的單例。需指定統一加載器或使用 JNDI 共享。
  • PetStore ServiceLocator 案例:Web 層用單例定位 EJB,EJB 層因跨 JVM 不能用單例,故分離為兩個 ServiceLocator。

選擇建議

一般情況首選 靜態內部類;要求極高安全性(防反射/序列化)選 枚舉;極簡場景可用 餓漢式。

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