设计模式-单例模式

单例模式

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 小时前
RK3528 V4L2 框架 UVC 接口自动获取 H.264 / MJPEG / YUYV 格式:从内核采集到硬解分发
java·网络·实时音视频·视频编解码·h.264
171320330计算机毕设编程1 小时前
计算机毕业设计 基于YOLO改进算法的车辆特征识别系统设计与实现--lw
java·大数据·python·sql·算法
badhope1 小时前
Spring AI Alibaba停更:Java程序员的信任,还能被辜负几次?
java·spring
const_qiu1 小时前
第一章 1.1-1.2:基础模型调用与 TypeScript 入门 —— Java 开发者的视角
java·javascript·typescript
Wang's Blog2 小时前
Java 项目实战: 交友项目 - Dubbo 负载均衡策略与实战验证
java·dubbo·交友
SL_staff2 小时前
销售知识库7天落地实践:面向业务侧的零代码嵌入方案
java·开源·产品
GreatSQL社区2 小时前
主从复制SQL线程中断——字符集砸出的坑
java·数据库·算法
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 入门案例:服务提供者搭建总结
java·交友
hudd6682 小时前
JavaEE 初阶 - 多线程(进阶)
java·开发语言·java-ee
Pniubi2 小时前
区分Java创建线程池、多线程
java·线程·线程池·多线程·并发