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

Java 多執行緒環境下單例模式實作:雙重檢查鎖與靜態內部類優雅寫法

     編輯:Java 相關知識

單例模式基本要素

  1. 私有靜態實例變數
  2. 私有建構子
  3. 公有靜態獲取實例方法

懶漢式 (Lazy) - 線程不安全版

public class LazySingleton {
    private static LazySingleton instance;
    private LazySingleton() {}
    public static LazySingleton getInstance() {
        if (instance == null) instance = new LazySingleton(); // 多線程下會創建多個實例
        return instance;
    }
}

解決方案比較

1. 同步方法 (效能差)

public synchronized static LazySingleton getInstance() { ... }

2. 雙重檢查鎖 (DCL) - 推薦

public class LazySingleton {
    private static volatile LazySingleton instance; // volatile 禁止指令重排
    private LazySingleton() {}
    public static LazySingleton getInstance() {
        if (instance == null) { // 第一次檢查,無鎖讀取
            synchronized (LazySingleton.class) {
                if (instance == null) { // 第二次檢查,鎖內創建
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }
}

關鍵點:volatile 確保 instance = new ... 的寫入對其他執行緒可見,避免半初始化物件被返回。

3. 靜態內部類 (Static Inner Class) - 最優雅

public class Singleton {
    private Singleton() {}
    private static class Holder {
        static final Singleton INSTANCE = new Singleton(); // 類載入時初始化,JVM 保證線程安全
    }
    public static Singleton getInstance() { return Holder.INSTANCE; }
}

優點:利用類載入機制天然線程安全、延遲載入 (調用 getInstance 才載入 Holder)、代碼簡潔無鎖。

實戰應用:線程池工廠單例

public class ThreadPoolFactoryUtil {
    private ExecutorService executorService;
    private ThreadPoolFactoryUtil() {
        int nThreads = Runtime.getRuntime().availableProcessors();
        executorService = Executors.newFixedThreadPool(nThreads);
    }
    private static class SingletonContainer {
        static final ThreadPoolFactoryUtil INSTANCE = new ThreadPoolFactoryUtil();
    }
    public static ThreadPoolFactoryUtil getUtil() { return SingletonContainer.INSTANCE; }
    public ExecutorService getExecutorService() { return executorService; }
}

在高併發循環任務中,透過單例確保全域僅有一個線程池,避免資源耗盡。

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