確保一個類在全局範圍內僅有一個實例,並提供一個全局訪問點獲取該實例。
特點:類加載時立即實例化,線程安全,調用效率高,但無法延遲加載。
public class Singleton01 {
private static Singleton01 instance = new Singleton01();
private Singleton01() {}
public static Singleton01 getInstance() { return instance; }
}
靜態變量在類加載時初始化,JVM 保證只加載一次,天然線程安全。缺點:若類被加載但未使用,造成資源浪費。
特點:首次調用時創建,延遲加載,但同步鎖導致併發效率低。
public class Singleton02 {
private static Singleton02 instance = null;
private Singleton02() {}
public static synchronized Singleton02 getInstance() {
if (instance == null) instance = new Singleton02();
return instance;
}
}
特點:嘗試兼顧延遲加載與高併發,但因 JVM 指令重排序可能導致問題,不推薦使用(除非加 volatile)。
public class Singleton03 {
private volatile static Singleton03 instance = null;
private Singleton03() {}
public static Singleton03 getInstance() {
if (instance == null) {
synchronized (Singleton03.class) {
if (instance == null) instance = new Singleton03();
}
}
return instance;
}
}
特點:推薦使用。線程安全、調用效率高、實現延遲加載,完美結合餓漢與懶漢優點。
public class Singleton04 {
private Singleton04() {}
public static Singleton04 getInstance() { return Inner.instance; }
private static class Inner {
private static final Singleton04 instance = new Singleton04();
}
}
外部類無靜態屬性,不會在加載時實例化;調用 getInstance 時才加載內部類,類加載過程線程安全;static final 保證唯一實例。
特點:實現最簡潔,JVM 根本層面保證單例,天然防反射與序列化破壞,但無延遲加載。
public enum Singleton05 {
INSTANCE;
public void operation() { /* 業務邏輯 */ }
}
readResolve() 返回原實例。