Java 中的單例類(Singleton)應(yīng)用場(chǎng)景分析
Java 中的單例類(Singleton)
單例類是一種設(shè)計(jì)模式,確保一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)全局訪問(wèn)點(diǎn)。
單例模式的核心特點(diǎn)
- 唯一實(shí)例:類只能創(chuàng)建一個(gè)對(duì)象實(shí)例
- 全局訪問(wèn):提供全局訪問(wèn)點(diǎn)獲取該實(shí)例
- 自行實(shí)例化:類自己負(fù)責(zé)創(chuàng)建自己的實(shí)例
- 構(gòu)造器私有:防止外部通過(guò) new 創(chuàng)建實(shí)例
單例模式的實(shí)現(xiàn)方式
1. 餓漢式(Eager Initialization)
public class EagerSingleton {
// 類加載時(shí)就創(chuàng)建實(shí)例
private static final EagerSingleton instance = new EagerSingleton();
// 私有構(gòu)造器
private EagerSingleton() {
// 防止反射攻擊
if (instance != null) {
throw new RuntimeException("單例模式禁止反射創(chuàng)建實(shí)例");
}
}
// 全局訪問(wèn)點(diǎn)
public static EagerSingleton getInstance() {
return instance;
}
public void showMessage() {
System.out.println("餓漢式單例");
}
}優(yōu)點(diǎn):簡(jiǎn)單、線程安全
缺點(diǎn):如果實(shí)例未被使用,會(huì)造成內(nèi)存浪費(fèi)
2. 懶漢式(Lazy Initialization)
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 線程不安全版本
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}3. 線程安全的懶漢式
public class ThreadSafeSingleton {
private static volatile ThreadSafeSingleton instance;
private ThreadSafeSingleton() {}
// 方法同步(性能較差)
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}4. 雙重檢查鎖(Double-Checked Locking)
public class DoubleCheckedSingleton {
// 使用 volatile 保證可見性和禁止指令重排序
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {}
public static DoubleCheckedSingleton getInstance() {
if (instance == null) { // 第一次檢查
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) { // 第二次檢查
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}5. 靜態(tài)內(nèi)部類(推薦使用)
public class InnerClassSingleton {
private InnerClassSingleton() {
// 防止反射攻擊
if (SingletonHolder.INSTANCE != null) {
throw new RuntimeException("單例模式禁止反射創(chuàng)建實(shí)例");
}
}
// 靜態(tài)內(nèi)部類在第一次被引用時(shí)才會(huì)加載
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
public void showMessage() {
System.out.println("靜態(tài)內(nèi)部類單例");
}
}優(yōu)點(diǎn):懶加載、線程安全、性能好
6. 枚舉單例(最安全的方式)
public enum EnumSingleton {
INSTANCE;
public void showMessage() {
System.out.println("枚舉單例");
}
// 可以添加其他方法
public void doSomething() {
System.out.println("執(zhí)行某些操作");
}
}
// 使用方式
EnumSingleton.INSTANCE.showMessage();優(yōu)點(diǎn):
- 絕對(duì)防止多次實(shí)例化
- 自動(dòng)支持序列化機(jī)制
- 防止反射攻擊
單例模式的應(yīng)用場(chǎng)景
// 1. 配置管理器
public class ConfigurationManager {
private static class Holder {
static final ConfigurationManager INSTANCE = new ConfigurationManager();
}
private Properties config;
private ConfigurationManager() {
// 加載配置文件
config = new Properties();
try {
config.load(getClass().getResourceAsStream("/config.properties"));
} catch (IOException e) {
throw new RuntimeException("加載配置文件失敗", e);
}
}
public static ConfigurationManager getInstance() {
return Holder.INSTANCE;
}
public String getProperty(String key) {
return config.getProperty(key);
}
}
// 2. 數(shù)據(jù)庫(kù)連接池
public class DatabaseConnectionPool {
private static final DatabaseConnectionPool instance = new DatabaseConnectionPool();
private List<Connection> connections;
private DatabaseConnectionPool() {
// 初始化連接池
connections = new ArrayList<>();
// ... 創(chuàng)建數(shù)據(jù)庫(kù)連接
}
public static DatabaseConnectionPool getInstance() {
return instance;
}
public Connection getConnection() {
// 從連接池獲取連接
return connections.isEmpty() ? null : connections.remove(0);
}
public void releaseConnection(Connection conn) {
connections.add(conn);
}
}
// 3. 日志記錄器
public class Logger {
private static volatile Logger instance;
private Logger() {
// 初始化日志系統(tǒng)
}
public static Logger getInstance() {
if (instance == null) {
synchronized (Logger.class) {
if (instance == null) {
instance = new Logger();
}
}
}
return instance;
}
public void log(String message) {
System.out.println("[LOG] " + new Date() + ": " + message);
}
}單例模式的注意事項(xiàng)
1. 序列化問(wèn)題
public class SerializableSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private static SerializableSingleton instance = new SerializableSingleton();
private SerializableSingleton() {}
public static SerializableSingleton getInstance() {
return instance;
}
// 防止反序列化創(chuàng)建新實(shí)例
protected Object readResolve() {
return getInstance();
}
}2. 反射攻擊防護(hù)
public class ReflectionSafeSingleton {
private static ReflectionSafeSingleton instance;
private static boolean initialized = false;
private ReflectionSafeSingleton() {
synchronized (ReflectionSafeSingleton.class) {
if (initialized) {
throw new RuntimeException("單例模式禁止反射創(chuàng)建實(shí)例");
}
initialized = true;
}
}
public static ReflectionSafeSingleton getInstance() {
if (instance == null) {
synchronized (ReflectionSafeSingleton.class) {
if (instance == null) {
instance = new ReflectionSafeSingleton();
}
}
}
return instance;
}
}3. 克隆防護(hù)
public class CloneSafeSingleton implements Cloneable {
private static final CloneSafeSingleton instance = new CloneSafeSingleton();
private CloneSafeSingleton() {}
public static CloneSafeSingleton getInstance() {
return instance;
}
// 防止克隆
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("單例模式禁止克隆");
}
}總結(jié)
| 實(shí)現(xiàn)方式 | 線程安全 | 懶加載 | 性能 | 推薦度 |
|---|---|---|---|---|
| 餓漢式 | ? | ? | 好 | ★★★ |
| 懶漢式(同步) | ? | ? | 差 | ★★ |
| 雙重檢查鎖 | ? | ? | 好 | ★★★★ |
| 靜態(tài)內(nèi)部類 | ? | ? | 好 | ★★★★★ |
| 枚舉 | ? | ? | 好 | ★★★★★ |
最佳實(shí)踐建議:
- 如果需要懶加載:使用靜態(tài)內(nèi)部類方式
- 如果不需要懶加載:使用枚舉方式(最安全)
- 避免使用簡(jiǎn)單的懶漢式(線程不安全)
- 考慮序列化、反射、克隆等安全問(wèn)題
到此這篇關(guān)于Java 中的單例類(Singleton)應(yīng)用場(chǎng)景分析的文章就介紹到這了,更多相關(guān)java單例類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java鎖機(jī)制的使用與實(shí)戰(zhàn)分析
本文全面探討了Java中的鎖機(jī)制,包括synchronized關(guān)鍵字、內(nèi)置鎖、顯示鎖、讀寫鎖、條件變量、樂觀鎖、悲觀鎖、自旋鎖和StampedLock,每個(gè)鎖機(jī)制都有其特點(diǎn)和適用場(chǎng)景,開發(fā)者應(yīng)根據(jù)具體需求選擇合適的鎖實(shí)現(xiàn),以確保多線程程序的并發(fā)安全和性能2026-01-01
Java實(shí)現(xiàn)獲取客戶端真實(shí)IP方法小結(jié)
本文給大家匯總介紹了2種使用java實(shí)現(xiàn)獲取客戶端真實(shí)IP的方法,主要用于獲取使用了代理訪問(wèn)的來(lái)訪者的IP,有需要的小伙伴可以參考下。2016-03-03
Java線程實(shí)現(xiàn)的三種方式詳細(xì)解析
這篇文章主要介紹了Java線程實(shí)現(xiàn)的三種方式詳細(xì)解析,Java多線程實(shí)現(xiàn)方式主要有三種,繼承Thread類、實(shí)現(xiàn)Runnable接口、使用ExecutorService、Callable、Future實(shí)現(xiàn)有返回結(jié)果的多線程,需要的朋友可以參考下2023-12-12
PowerJob的TransportServiceAware工作流程源碼解讀
這篇文章主要介紹了PowerJob的TransportServiceAware工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01

