设计模式-单例模式

单例模式

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)。

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

相关推荐
雷渊1 分钟前
mysql-EXPLAIN执行计划分析
java·后端·面试
dr李四维1 小时前
Java在小米SU7 Ultra汽车中的技术赋能
java·人工智能·安卓·智能驾驶·互联·小米su7ultra·hdfs架构
RainbowSea1 小时前
130道基础OJ编程题之: 78~88
java
松树戈1 小时前
IDEA Commit 模态提交界面关闭VS开启对比
java·ide·intellij-idea
谦行1 小时前
前端视角 Java Web 入门手册 4.4:Web 开发基础—— Listener
java·后端
jk_1012 小时前
MATLAB中strip函数用法
java·服务器·数据库
一弓虽2 小时前
maven学习
java·学习·github·maven
24k小善2 小时前
Flink Forward Asia 2024 大会 内容整理
java·大数据·flink
xiaozaq2 小时前
在Eclipse中安装Lombok插件
java·python·eclipse
是姜姜啊!3 小时前
服务熔断组件sentinel,监控服务-springboot-admin-ui
java·服务器