Java 中的单例类(Singleton)应用场景分析
作者:总会落叶
单例类是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点,本文给大家介绍Java中的单例类(Singleton)应用场景分析,感兴趣的朋友跟随小编一起看看吧
Java 中的单例类(Singleton)
单例类是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。
单例模式的核心特点
- 唯一实例:类只能创建一个对象实例
- 全局访问:提供全局访问点获取该实例
- 自行实例化:类自己负责创建自己的实例
- 构造器私有:防止外部通过 new 创建实例
单例模式的实现方式
1. 饿汉式(Eager Initialization)
public class EagerSingleton {
// 类加载时就创建实例
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造器
private EagerSingleton() {
// 防止反射攻击
if (instance != null) {
throw new RuntimeException("单例模式禁止反射创建实例");
}
}
// 全局访问点
public static EagerSingleton getInstance() {
return instance;
}
public void showMessage() {
System.out.println("饿汉式单例");
}
}优点:简单、线程安全
缺点:如果实例未被使用,会造成内存浪费
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. 静态内部类(推荐使用)
public class InnerClassSingleton {
private InnerClassSingleton() {
// 防止反射攻击
if (SingletonHolder.INSTANCE != null) {
throw new RuntimeException("单例模式禁止反射创建实例");
}
}
// 静态内部类在第一次被引用时才会加载
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
public void showMessage() {
System.out.println("静态内部类单例");
}
}优点:懒加载、线程安全、性能好
6. 枚举单例(最安全的方式)
public enum EnumSingleton {
INSTANCE;
public void showMessage() {
System.out.println("枚举单例");
}
// 可以添加其他方法
public void doSomething() {
System.out.println("执行某些操作");
}
}
// 使用方式
EnumSingleton.INSTANCE.showMessage();优点:
- 绝对防止多次实例化
- 自动支持序列化机制
- 防止反射攻击
单例模式的应用场景
// 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. 数据库连接池
public class DatabaseConnectionPool {
private static final DatabaseConnectionPool instance = new DatabaseConnectionPool();
private List<Connection> connections;
private DatabaseConnectionPool() {
// 初始化连接池
connections = new ArrayList<>();
// ... 创建数据库连接
}
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() {
// 初始化日志系统
}
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);
}
}单例模式的注意事项
1. 序列化问题
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;
}
// 防止反序列化创建新实例
protected Object readResolve() {
return getInstance();
}
}2. 反射攻击防护
public class ReflectionSafeSingleton {
private static ReflectionSafeSingleton instance;
private static boolean initialized = false;
private ReflectionSafeSingleton() {
synchronized (ReflectionSafeSingleton.class) {
if (initialized) {
throw new RuntimeException("单例模式禁止反射创建实例");
}
initialized = true;
}
}
public static ReflectionSafeSingleton getInstance() {
if (instance == null) {
synchronized (ReflectionSafeSingleton.class) {
if (instance == null) {
instance = new ReflectionSafeSingleton();
}
}
}
return instance;
}
}3. 克隆防护
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("单例模式禁止克隆");
}
}总结
| 实现方式 | 线程安全 | 懒加载 | 性能 | 推荐度 |
|---|---|---|---|---|
| 饿汉式 | ✅ | ❌ | 好 | ★★★ |
| 懒汉式(同步) | ✅ | ✅ | 差 | ★★ |
| 双重检查锁 | ✅ | ✅ | 好 | ★★★★ |
| 静态内部类 | ✅ | ✅ | 好 | ★★★★★ |
| 枚举 | ✅ | ❌ | 好 | ★★★★★ |
最佳实践建议:
- 如果需要懒加载:使用静态内部类方式
- 如果不需要懒加载:使用枚举方式(最安全)
- 避免使用简单的懒汉式(线程不安全)
- 考虑序列化、反射、克隆等安全问题
到此这篇关于Java 中的单例类(Singleton)应用场景分析的文章就介绍到这了,更多相关java单例类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
