Holder 方式 和 枚舉方式 可以線程安全的實現單例模式。
Holder 方式 藉助於類加載 的初始化階段<clinit>() 方法是同步方法。
枚舉方式 是因爲枚舉類型不能繼承且只能被實例化一次。
1. Holder 方式實現單例模式
類加載 的初始化階段<clinit>() 方法是同步方法,在類中設置一個靜態類,將唯一實例放在靜態類中,第一次訪問實例的時候內部類初始化,即初始化唯一實例。代碼如下所示:
public final class HolderSingleton {
// 實例變量
private String value;
private HolderSingleton() {
System.out.println("初始化");
}
// 靜態內部類持有實例,並可直接被初始化
private static class Holder {
private static HolderSingleton instance = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return Holder.instance;
}
public static void main(String[] args) {
HolderSingleton holderSingleton1 = HolderSingleton.getInstance();
HolderSingleton holderSingleton2 = HolderSingleton.getInstance();
System.out.println(holderSingleton1 == holderSingleton2);
}
}
測試截圖如下所示:
2. 枚舉方式實現單例模式
枚舉類型不能繼承且只能被實例化一次,枚舉方式實現單例模式如下所示。
package Singleton;
public enum EnumSingleton {
INSTANCE;
private String value;
EnumSingleton() {
System.out.println("初始化");
}
// public static void method() {
//
// }
public static EnumSingleton getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
//EnumSingleton.method();
EnumSingleton enumSingleton1 = EnumSingleton.getInstance();
EnumSingleton enumSingleton2 = EnumSingleton.getInstance();
System.out.println(enumSingleton1 == enumSingleton2);
}
}
測試運行截圖:
調用靜態方法就會導致唯一實例初始化,測試代碼如下所示。
package Singleton;
public enum EnumSingleton {
INSTANCE;
private String value;
EnumSingleton() {
System.out.println("初始化");
}
public static void method() {
}
public static EnumSingleton getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
EnumSingleton.method();
}
}
虛擬機規範有且只有下面5種情況立即對類進行“初始化”。
(1) 使用 new 關鍵字 ;Get static,Put static 即設置或訪問靜態變量 (類的靜態字段 被 final 修飾,加入常量池的除外);Invoke static 調用靜態方法 。
(2)使用 java.lang.reflect 包的方法對類進行反射的時候。
(3)初始一個類,發現父類沒有進行初始化,先初始化父類。
(4)虛擬機啓動時, 用戶需要制定一個要執行的主類,先初始化主類。
(5)Java 的動態語言支持時,如果一個 java.lang.invoke.MethodHandle 實例最後的解析結果 REF_getStatic、REF_setStatic、REF_invokeStatic 方法的句柄,並且該句柄的方法所對應類沒有進行過初始化,則需要先觸發其初始化。
參考文獻
- 深入理解Java虛擬機:JVM高級特性與最佳實踐 / 周志明著. —— 2 版 . —— 北京:機械工業出版社,2013.6 (2019.1重印)
- Java高併發編程詳解:多線程與架構設計 / 汪文君著——北京:機械工業出版社,2018.5