单例设计模式

单例模式是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。以下是几种实现单例模式的常见方式,每种方式都有其特点和适用场景。

1. 懒汉式(线程不安全)

这种实现方式在第一次调用时创建实例,但不适用于多线程环境。

java 复制代码
public class SingletonLazy {
    private static SingletonLazy instance;

    private SingletonLazy() {
        // 私有构造函数
    }

    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

缺点:多线程环境下可能会创建多个实例。

2. 懒汉式(线程安全,使用synchronized)

通过在获取实例的方法上加锁保证线程安全。

java 复制代码
public class SingletonLazySafe {
    private static SingletonLazySafe instance;

    private SingletonLazySafe() {
        // 私有构造函数
    }

    public static synchronized SingletonLazySafe getInstance() {
        if (instance == null) {
            instance = new SingletonLazySafe();
        }
        return instance;
    }
}

缺点:性能较低,每次访问都需要加锁。

3. 双重检查锁(DCL)

通过减少加锁范围,提升性能,同时保证线程安全。

java 复制代码
public class SingletonDCL {
    private static volatile SingletonDCL instance;

    private SingletonDCL() {
        // 私有构造函数
    }

    public static SingletonDCL getInstance() {
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}

优点:高效,线程安全,推荐使用。

4. 饿汉式

在类加载时就创建实例,线程安全。

java 复制代码
public class SingletonEager {
    private static final SingletonEager INSTANCE = new SingletonEager();

    private SingletonEager() {
        // 私有构造函数
    }

    public static SingletonEager getInstance() {
        return INSTANCE;
    }
}

5. 静态内部类

利用类加载机制实现延迟加载和线程安全。

java 复制代码
public class SingletonStaticInner {
    private SingletonStaticInner() {
        // 私有构造函数
    }

    private static class Holder {
        private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();
    }

    public static SingletonStaticInner getInstance() {
        return Holder.INSTANCE;
    }
}

优点:线程安全,延迟加载,推荐使用。

6. 枚举实现(推荐)

通过枚举类型实现单例,是最优雅的方式之一,同时也是线程安全的。

java 复制代码
public enum SingletonEnum {
    INSTANCE;

    public void doSomething() {
        System.out.println("SingletonEnum is working!");
    }
}

优点:防止反射和序列化破坏单例。

7. 防止反射攻击

对于非枚举的单例模式,可以通过在构造函数中添加防御逻辑来防止反射攻击。

java 复制代码
public class SingletonWithReflectionSafe {
    private static final SingletonWithReflectionSafe INSTANCE = new SingletonWithReflectionSafe();

    private SingletonWithReflectionSafe() {
        if (INSTANCE != null) {
            throw new RuntimeException("Cannot create instance via reflection!");
        }
    }

    public static SingletonWithReflectionSafe getInstance() {
        return INSTANCE;
    }
}

选择建议

简单线程安全:优先考虑静态内部类或双重检查锁。

最安全(防反射和序列化攻击):使用枚举实现。

性能不敏感、初始化成本低:可以使用饿汉式。

相关推荐
二哈赛车手2 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
栗子~~3 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
YDS8293 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
未若君雅裁5 小时前
MyBatis 一级缓存、二级缓存与清理机制
java·缓存·mybatis
AI人工智能+电脑小能手5 小时前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
阿维的博客日记5 小时前
Nacos 为什么能让配置动态生效?(涉及 @RefreshScope 注解)
java·spring
雨辰AI6 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
辰海Coding7 小时前
MiniSpring框架学习-完成的 IoC 容器
java·spring boot·学习·架构
小小编程路7 小时前
C++ 多线程与并发
java·jvm·c++
AI视觉网奇7 小时前
linux 检索库 判断库是否支持
java·linux·服务器