设计模式-单例模式

单例模式

Java 实现单例模式的方式主要有以下几种,每种方式都有其优缺点和适用场景。


1. 饿汉式(Eager Initialization)

实现方式

java 复制代码
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {} // 私有构造方法,防止外部实例化
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

优缺点

优点

  • 实现简单,类加载时即创建实例,线程安全。
  • 访问速度快,调用 getInstance() 方法不会有同步开销。

缺点

  • 可能造成资源浪费:即使实例可能长期未使用,仍然会在类加载时创建。

适用场景

  • 对象创建成本低 ,且类会被频繁使用的场景(如工具类)。

2. 懒汉式(Lazy Initialization,非线程安全)

实现方式

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

    private Singleton() {}

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

优缺点

优点

  • 只有在第一次调用时才创建实例,节省资源。

缺点

  • 非线程安全 :多个线程同时调用 getInstance() 可能导致多个实例被创建。

适用场景

  • 单线程环境 ,或者不在多线程场景下使用

3. 线程安全的懒汉式(同步方法)

实现方式

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

    private Singleton() {}

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

优缺点

优点

  • 线程安全,可确保只有一个实例被创建。

缺点

  • synchronized 关键字会影响性能 ,每次调用 getInstance() 都会加锁。

适用场景

  • 需要保证线程安全 ,但实例创建不会频繁调用的场景。

4. 双重检查锁(Double-Checked Locking,推荐)

实现方式

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

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) { // 第一次检查
            synchronized (Singleton.class) {
                if (instance == null) { // 第二次检查
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

优缺点

优点

  • 线程安全,只有在第一次调用时才会加锁,后续调用不会影响性能。
  • 结合了懒加载高效访问的优点。

缺点

  • 需要使用 volatile 防止指令重排序,Java 1.5 之前的版本不支持。

适用场景

  • 多线程环境 ,且性能要求较高的场景。

5. 静态内部类(推荐)

实现方式

java 复制代码
public class Singleton {
    private Singleton() {}

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

优缺点

优点

  • 线程安全 ,利用 JVM 类加载机制保证只会初始化一次。
  • 只有在调用 getInstance() 时才会创建实例,节省资源(懒加载)。
  • 无锁,性能高。

缺点

  • 无法传递参数,如果需要参数化实例,则无法使用该方法。

适用场景

  • 高并发环境 ,且希望使用懒加载的场景。

6. 枚举单例(最推荐)

实现方式

java 复制代码
public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("Do something...");
    }
}

优缺点

优点

  • 线程安全,由 JVM 保证。
  • 防止反序列化破坏单例,因为枚举不会创建新的实例。
  • 代码最简洁,推荐使用。

缺点

  • 无法懒加载,类加载时即创建实例。
  • 不能继承其他类(但可以实现接口)。

适用场景

  • 绝对保证单例性 的场景,如 数据库连接管理、日志管理器等。

7. 通过 ThreadLocal 实现(每个线程单例)

实现方式

java 复制代码
public class ThreadLocalSingleton {
    private static final ThreadLocal<ThreadLocalSingleton> instance =
        ThreadLocal.withInitial(ThreadLocalSingleton::new);

    private ThreadLocalSingleton() {}

    public static ThreadLocalSingleton getInstance() {
        return instance.get();
    }
}

优缺点

优点

  • 线程隔离,每个线程都有自己独立的实例。
  • 避免了全局同步,适用于多线程数据隔离场景

缺点

  • 无法做到全局唯一单例 ,只在单个线程内保持单例

适用场景

  • 每个线程需要独立状态 的场景,如用户会话、数据库连接

总结

方式 线程安全 是否懒加载 优点 缺点 适用场景
饿汉式 实现简单,访问快 可能造成资源浪费 适用于常用单例
懒汉式 按需加载,节省资源 线程不安全 仅限单线程
同步懒汉 线程安全 synchronized 影响性能 适用于低频率调用
双重检查锁 线程安全,性能优 代码较复杂 推荐,高并发环境
静态内部类 线程安全,懒加载 无法传参 推荐,JVM 保证
枚举单例 最安全,防反序列化 不能继承类 最推荐,绝对单例
ThreadLocal 线程隔离 不是全局单例 适用于每线程独立实例

如果要保证绝对的单例性 ,推荐 枚举单例Enum)。

如果需要懒加载且高性能 ,推荐 静态内部类双重检查锁

相关推荐
龙虾PRO1 小时前
能源与股票量化核心差异,AI全链路落地实操手册
java·面试·职场和发展
llwszx1 小时前
【Java/Go后端手撸原生Agent(第九篇):Plan-and-Execute规划模式——从“走一步看一步“到“先谋后动“】
java·python·golang·agent开发·plan模式·规划执行模式
ZJH__GO2 小时前
网络编程v2--多客户端互通
java·运维·服务器·开发语言·计算机网络
霸道流氓气质2 小时前
SpringBoot中基于 AES-GCM + KMS 密钥管理的数据加解密 Starter 实践
java·数据库·spring boot
Gofarlic_OMS2 小时前
NX浮动许可调度黑名单机制,对比两款谁更合理
java·大数据·运维·开源·制造
乐观的Terry2 小时前
8、发布系统-完整流水线的核心
java·spring boot·spring·spring cloud
Alexalbb2 小时前
从角色过滤到可审计授权:单体系统数据权限设计复盘与演进
java
万亿少女的梦1683 小时前
基于Spring Boot的游戏交易管理系统设计与实现
java·spring boot·mysql·系统设计·交易管理
闲猫3 小时前
Agent工程实践:从WorkFlow到多Agent协作的落地笔记
java·服务器·前端
笨蛋不要掉眼泪3 小时前
Java虚拟机:常用参数
java·开发语言·python