Java 23中設計模式之單例模式7種實現方式
一、懶漢式(執行緒不安全)
package com.java.singleton; //懶漢式 執行緒不安全 public class LazySingleton { //私有構造方法 只允許在內部進行例項的建立 private LazySingleton() { } private static LazySingleton instance = null; //建立例項 public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
二、懶漢式(執行緒安全)
package com.java.singleton; //懶漢式 執行緒安全 public class SynchronizedLazySingleton { //私有構造方法 只允許在內部進行例項的建立 private SynchronizedLazySingleton() { } private static SynchronizedLazySingleton instance = null; //建立例項執行緒安全 public static synchronized SynchronizedLazySingleton getInstance() { if (instance == null) { instance = new SynchronizedLazySingleton(); } return instance; } }
三、餓漢式(執行緒安全)
package com.java.singleton; //餓漢式 public class HungrySingleton { //私有構造方法 只允許在內部進行例項的建立 private HungrySingleton() { } //靜態初始化 由JVM保證執行緒安全 private static HungrySingleton instance = new HungrySingleton(); //建立例項 public static HungrySingleton getInstance() { return instance; } }
四、快取實現(執行緒不安全)
package com.java.singleton; import java.util.HashMap; import java.util.Map; //執行緒不安全 快取實現 public class CacheSingleton { //私有構造方法 只允許在內部進行例項的建立 private CacheSingleton() { } //構造快取容器 private static Map<String, CacheSingleton> map = new HashMap<>(); //構造預設的存放key private static final String DEFAULT_KEY = "Cache"; //建立例項 public static CacheSingleton getInstance() { //先從快取中取 沒有就建立並放入快取有就返回 CacheSingleton instance = (CacheSingleton) map.get(DEFAULT_KEY); if (instance == null) { instance = new CacheSingleton(); map.put(DEFAULT_KEY, instance); } return instance; } }
五、雙重檢查加鎖(懶漢式 執行緒安全的進一步優化)
package com.java.singleton; //雙重檢查加鎖懶漢式在方法上加synchronized的進一步優化 public class DoubleCheckedLockingSingleton { //私有構造方法 只允許在內部進行例項的建立 private DoubleCheckedLockingSingleton() { } //volatile 修飾的變數不會被本地執行緒快取 對該變數的讀寫直接作用於共享記憶體 類似於互斥鎖 private volatile static DoubleCheckedLockingSingleton instance = null; //建立例項 public static DoubleCheckedLockingSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckedLockingSingleton.class) { if (instance == null) { instance = new DoubleCheckedLockingSingleton(); } } } return instance; } }
六、 Lazy Initialization Holder Class實現單例
package com.java.singleton; //靜態內部類 Lazy Initialization Holder Class public class LazyInitializationHolderClassSingleton { //私有構造方法 只允許在內部進行例項的建立 private LazyInitializationHolderClassSingleton() { } /* * 靜態成員式內部類 該內部類的例項物件與外部類的例項無繫結關係 * 有且只有在LazyInitializationHolder被呼叫instance時 在會對物件例項進行裝載 * 從而實現延時載入 */ private static class LazyInitializationHolder { /* * 靜態初始化器 由JVM保證執行緒安全 * */ private static LazyInitializationHolderClassSingleton instance = new LazyInitializationHolderClassSingleton(); } //建立例項 public static LazyInitializationHolderClassSingleton getInstance() { return LazyInitializationHolder.instance; } }
七、列舉實現單例
package com.java.singleton; public enum EnumSingleton { //列舉類的每個元素 都代表一個單例 uniqueEnumSingleton; publicvoid method() { System.out.println("EnumSingleton"+uniqueEnumSingleton.hashCode()); } }
八、測試類
package com.java.singleton; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SingletonApplicationTests { @Test public void testCacheSingleton() { for (int i = 0; i < 3; i++) { System.out.println("CacheSingleton\t" + CacheSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testDoubleCheckedLockingSingleton() { for (int i = 0; i < 3; i++) { System.out.println("DoubleCheckedLockingSingleton\t" + DoubleCheckedLockingSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testEnumSingleton() { for (int i = 0; i < 3; i++) { EnumSingleton.uniqueEnumSingleton.method(); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testHungrySingleton() { for (int i = 0; i < 3; i++) { System.out.println("HungrySingleton\t" + HungrySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testLazyInitializationHolderClassSingleton() { for (int i = 0; i < 3; i++) { System.out.println("LazyInitializationHolderClassSingleton\t" + LazyInitializationHolderClassSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testLazySingleton() { for (int i = 0; i < 3; i++) { System.out.println("LazySingleton\t" + LazySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testSynchronizedLazySingleton() { for (int i = 0; i < 3; i++) { System.out.println("SynchronizedLazySingleton\t" + SynchronizedLazySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } }
九、測試結果
一、懶漢式(執行緒不安全)
package com.java.singleton; //懶漢式 執行緒不安全 public class LazySingleton { //私有構造方法 只允許在內部進行例項的建立 private LazySingleton() { } private static LazySingleton instance = null; //建立例項 public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } }
二、懶漢式(執行緒安全)
package com.java.singleton; //懶漢式 執行緒安全 public class SynchronizedLazySingleton { //私有構造方法 只允許在內部進行例項的建立 private SynchronizedLazySingleton() { } private static SynchronizedLazySingleton instance = null; //建立例項執行緒安全 public static synchronized SynchronizedLazySingleton getInstance() { if (instance == null) { instance = new SynchronizedLazySingleton(); } return instance; } }
三、餓漢式(執行緒安全)
package com.java.singleton; //餓漢式 public class HungrySingleton { //私有構造方法 只允許在內部進行例項的建立 private HungrySingleton() { } //靜態初始化 由JVM保證執行緒安全 private static HungrySingleton instance = new HungrySingleton(); //建立例項 public static HungrySingleton getInstance() { return instance; } }
四、快取實現(執行緒不安全)
package com.java.singleton; import java.util.HashMap; import java.util.Map; //執行緒不安全 快取實現 public class CacheSingleton { //私有構造方法 只允許在內部進行例項的建立 private CacheSingleton() { } //構造快取容器 private static Map<String, CacheSingleton> map = new HashMap<>(); //構造預設的存放key private static final String DEFAULT_KEY = "Cache"; //建立例項 public static CacheSingleton getInstance() { //先從快取中取 沒有就建立並放入快取有就返回 CacheSingleton instance = (CacheSingleton) map.get(DEFAULT_KEY); if (instance == null) { instance = new CacheSingleton(); map.put(DEFAULT_KEY, instance); } return instance; } }
五、雙重檢查加鎖(懶漢式 執行緒安全的進一步優化)
package com.java.singleton; //雙重檢查加鎖懶漢式在方法上加synchronized的進一步優化 public class DoubleCheckedLockingSingleton { //私有構造方法 只允許在內部進行例項的建立 private DoubleCheckedLockingSingleton() { } //volatile 修飾的變數不會被本地執行緒快取 對該變數的讀寫直接作用於共享記憶體 類似於互斥鎖 private volatile static DoubleCheckedLockingSingleton instance = null; //建立例項 public static DoubleCheckedLockingSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckedLockingSingleton.class) { if (instance == null) { instance = new DoubleCheckedLockingSingleton(); } } } return instance; } }
六、 Lazy Initialization Holder Class實現單例
package com.java.singleton; //靜態內部類 Lazy Initialization Holder Class public class LazyInitializationHolderClassSingleton { //私有構造方法 只允許在內部進行例項的建立 private LazyInitializationHolderClassSingleton() { } /* * 靜態成員式內部類 該內部類的例項物件與外部類的例項無繫結關係 * 有且只有在LazyInitializationHolder被呼叫instance時 在會對物件例項進行裝載 * 從而實現延時載入 */ private static class LazyInitializationHolder { /* * 靜態初始化器 由JVM保證執行緒安全 * */ private static LazyInitializationHolderClassSingleton instance = new LazyInitializationHolderClassSingleton(); } //建立例項 public static LazyInitializationHolderClassSingleton getInstance() { return LazyInitializationHolder.instance; } }
七、列舉實現單例
package com.java.singleton; public enum EnumSingleton { //列舉類的每個元素 都代表一個單例 uniqueEnumSingleton; publicvoid method() { System.out.println("EnumSingleton"+uniqueEnumSingleton.hashCode()); } }
八、測試類
package com.java.singleton; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SingletonApplicationTests { @Test public void testCacheSingleton() { for (int i = 0; i < 3; i++) { System.out.println("CacheSingleton\t" + CacheSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testDoubleCheckedLockingSingleton() { for (int i = 0; i < 3; i++) { System.out.println("DoubleCheckedLockingSingleton\t" + DoubleCheckedLockingSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testEnumSingleton() { for (int i = 0; i < 3; i++) { EnumSingleton.uniqueEnumSingleton.method(); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testHungrySingleton() { for (int i = 0; i < 3; i++) { System.out.println("HungrySingleton\t" + HungrySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testLazyInitializationHolderClassSingleton() { for (int i = 0; i < 3; i++) { System.out.println("LazyInitializationHolderClassSingleton\t" + LazyInitializationHolderClassSingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testLazySingleton() { for (int i = 0; i < 3; i++) { System.out.println("LazySingleton\t" + LazySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } @Test public void testSynchronizedLazySingleton() { for (int i = 0; i < 3; i++) { System.out.println("SynchronizedLazySingleton\t" + SynchronizedLazySingleton.getInstance()); } System.out.println("-------------------------------------------------------------------\n"); } }
九、測試結果