java设计模式:02-01-单例模式

单例模式(Singleton Pattern)

单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于需要全局唯一实例的场景,例如:

  • 日志记录(Logging):应用程序中的所有组件都需要记录日志,单例模式可以确保日志记录器的唯一实例。
  • 配置管理(Configuration Management):配置文件的读取和写入需要全局唯一实例,以避免不同组件之间的配置不一致。
  • 连接池(Connection Pooling):数据库连接池需要管理有限数量的连接实例,单例模式可以确保连接池的唯一实例。
  • 缓存(Caching):全局缓存需要唯一实例,以便于所有组件共享缓存数据。
  • 线程池(Thread Pool):线程池需要全局唯一实例,以确保系统中只有一个线程池在管理线程。

单例模式的多种实现方式

1. 饿汉式(Eager Initialization)

思想:在类加载时就创建单例实例,避免了多线程问题,但如果实例占用资源较大且不一定会用到,会造成资源浪费。

实现方式

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

    private SingletonEager() {
        // 防止实例化的私有构造函数
    }

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

优点

  • 实现简单。
  • 类加载时创建实例,线程安全。

缺点

  • 如果单例实例占用资源较大且未使用,会造成资源浪费。
2. 懒汉式(Lazy Initialization)

思想:在第一次需要实例时创建,避免资源浪费,但需要处理多线程问题。

实现方式

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

    private SingletonLazy() {
        // 防止实例化的私有构造函数
    }

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

优点

  • 实例在第一次使用时创建,节省资源。

缺点

  • 需要加锁以确保线程安全,性能开销较大。
3. 双重检查锁定(Double-Checked Locking)

思想:结合饿汉式和懒汉式的优点,第一次检查实例是否为 null,避免不必要的同步,提高性能。

实现方式

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. 静态内部类(Bill Pugh Singleton)

思想:利用类加载机制,只有在使用时才加载内部类,从而实现延迟加载和线程安全。

实现方式

java 复制代码
public class SingletonStaticInnerClass {
    private SingletonStaticInnerClass() {
        // 防止实例化的私有构造函数
    }

    private static class SingletonHelper {
        private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();
    }

    public static SingletonStaticInnerClass getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

优点

  • 实现简单。
  • 线程安全。
  • 延迟加载。

缺点

  • 无法进行细粒度控制。
5. 枚举单例(Enum Singleton)

思想:使用 Java 枚举类型的特性,枚举类的实例天生是单例。

实现方式

java 复制代码
public enum SingletonEnum {
    INSTANCE;

    public void someMethod() {
        // some method
    }
}

优点

  • 实现最简单。
  • 线程安全。
  • 防止反序列化创建新实例。

缺点

  • 枚举类型不灵活,无法进行细粒度控制。

总结

实现方式 优点 缺点
饿汉式(Eager Initialization) 实现简单,线程安全 可能造成资源浪费
懒汉式(Lazy Initialization) 实例在第一次使用时创建,节省资源 需要加锁以确保线程安全,性能开销较大
双重检查锁定(Double-Checked Locking) 提高了懒汉式的性能,减少同步开销 代码较为复杂
静态内部类(Bill Pugh Singleton) 实现简单,线程安全,延迟加载 无法进行细粒度控制
枚举单例(Enum Singleton) 实现最简单,线程安全,防止反序列化创建新实例 枚举类型不灵活,无法进行细粒度控制

不同的实现方式各有优劣,选择哪种实现方式应根据具体的应用场景和需求来决定。如果需要简单而且线程安全的实现,枚举单例是一个很好的选择。如果需要延迟加载且线程安全,静态内部类和双重检查锁定都是不错的选择。

相关推荐
消失的旧时光-19432 分钟前
Spring Boot 核心机制之 @Conditional:从原理到实战(一次讲透)
java·spring boot·后端
石榴树下的七彩鱼6 分钟前
智能抠图 API 接入实战:3 行代码实现图片自动去背景(Python / Java / PHP / JS)
java·图像处理·人工智能·python·php·api·抠图
知兀9 分钟前
【Result类】(使用/不使用<T> data的情况);自带静态方法、纯数据类;
java·开发语言
Seven9710 分钟前
【从0到1构建一个ClaudeAgent】协作-自主Agent
java
洋不写bug16 分钟前
Java线程(三):线程执行顺序问题、可重入锁、加锁操作解析,死锁解决
java·开发语言
kyriewen1125 分钟前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式·typescript·ecmascript·html5
lifallen30 分钟前
Flink Source / Sink Exactly-Once 边界分析
java·大数据·flink
xyyaihxl36 分钟前
将 vue3 项目打包后部署在 springboot 项目运行
java·spring boot·后端
kyriewen1 小时前
代码写成一锅粥?这5种设计模式让你的项目“起死回生”
前端·javascript·设计模式
0xDevNull1 小时前
Spring Boot 3.x 整合 Nacos 全栈实战教程
java·spring boot·nacos