目錄
餓漢式單例模式
懶漢式單例模式
Spring中的單例模式
關鍵差異對比
在Java和Spring中的應用場景
手寫案例
單例模式是一種創建型設計模式,其核心在于確保一個類僅有一個實例,并提供一個全局訪問點來獲取該實例。下面將詳細介紹餓漢式和懶漢式單例模式,以及它們在Java和Spring框架中的體現。
餓漢式單例模式
這種模式的特點是類加載時就創建實例,無需等待首次使用。它不存在線程安全問題,因為實例的創建是在類加載階段完成的。
Java實現示例:
public class EagerSingleton {private static final EagerSingleton INSTANCE = new EagerSingleton();private EagerSingleton() {}public static EagerSingleton getInstance() {return INSTANCE;}
}
懶漢式單例模式
懶漢式單例模式是在首次使用時才創建實例。不過,在多線程環境下,如果沒有合適的同步機制,就可能會創建多個實例。
非線程安全的Java實現示例:
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
線程安全的Java實現示例:
public class ThreadSafeLazySingleton {private static volatile ThreadSafeLazySingleton instance;private ThreadSafeLazySingleton() {}public static ThreadSafeLazySingleton getInstance() {if (instance == null) {synchronized (ThreadSafeLazySingleton.class) {if (instance == null) {instance = new ThreadSafeLazySingleton();}}}return instance;}
}
Spring中的單例模式
在Spring框架里,默認情況下,所有的bean都是以單例模式創建的,也就是在整個應用上下文中只存在一個實例。
Spring單例bean示例:
@Component
public class SpringSingleton {// Spring會自動管理這個bean的單例實例
}
獲取Spring單例bean的方式:
@Autowired
private SpringSingleton springSingleton;
關鍵差異對比
維度 | 餓漢式 | 懶漢式(線程安全) |
實例創建時機 | 類加載時 | 首次調用時 |
線程安全性 | 安全 | 安全 |
優點 | 實現簡單,無需考慮線程安全問題 | 延遲加載,節省資源 |
缺點 | 可能造成資源浪費 | 實現較為復雜,性能可能受影響 |
適用場景 | 實例創建成本低,且一定會被使用 | 實例創建成本高,或不一定會被使用 |
在Java和Spring中的應用場景
- Java中的應用:像日志記錄器、數據庫連接池這類需要全局唯一實例的場景,會用到單例模式。
- Spring中的應用:Spring框架默認將bean配置為單例,這樣可以減少內存開銷,同時保證狀態管理的一致性。
理解單例模式的不同實現方式以及它們在Java和Spring中的應用,有助于設計出高效且線程安全的應用程序。
手寫案例
public class Main { }// 單例模式 初始化bean// 餓漢式 單例初始化
// 在類首次加載時就進行初始化 不需要考慮線程安全問題
class Hungrybean{private static final Hungrybean INSTANCE = new Hungrybean();public static Hungrybean getInstance() {return INSTANCE;}
}// 懶漢式 單例初始化
// 在使用時再進行初始化 可能存在線程安全問題
class Lazybean{private static Lazybean INSTANCE ;public static Lazybean getInstance() {if(INSTANCE==null){INSTANCE=new Lazybean();}return INSTANCE;}
}// 鎖機制 修復了懶漢是的線程安全問題
class ThreadSafeLazybean{private static ThreadSafeLazybean INSTANCE;public static ThreadSafeLazybean getInstance(){if(INSTANCE==null){synchronized (ThreadSafeLazybean.class){if (INSTANCE==null){INSTANCE=new ThreadSafeLazybean();}return INSTANCE;}}}
}