创建型模式-单例模式

单例模式有两种常见的实现方式:饿汉式懒汉式。以下是它们的代码示例:

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)

在第一次调用 getInstance() 时才创建实例,适用于单例对象较耗资源且不一定每次都使用的场景。

2.1 线程不安全的懒汉式:
java 复制代码
public class SingletonLazy {
    // 延迟初始化
    private static SingletonLazy instance;

    // 私有构造方法
    private SingletonLazy() {}

    // 提供全局访问点(线程不安全)
    public static SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}

优点

  • 按需加载,节省资源

缺点

  • 线程不安全,多个线程可能同时创建多个实例
2.2 线程安全的懒汉式(同步方法):
java 复制代码
public class SingletonLazyThreadSafe {
    private static SingletonLazyThreadSafe instance;

    private SingletonLazyThreadSafe() {}

    // 通过同步锁保证线程安全
    public static synchronized SingletonLazyThreadSafe getInstance() {
        if (instance == null) {
            instance = new SingletonLazyThreadSafe();
        }
        return instance;
    }
}

优点

  • 线程安全,简单易懂

缺点

  • 每次获取实例都需要同步,性能开销较大
2.3 双重检查锁(Double-Check Locking):
java 复制代码
public class SingletonLazyDoubleCheck {
    private static volatile SingletonLazyDoubleCheck instance;

    private SingletonLazyDoubleCheck() {}

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

优点

  • 线程安全,且只在第一次创建时进行同步,性能较好

缺点

  • 代码较复杂,需要注意 volatile 的使用

3. 静态内部类(推荐使用)

静态内部类的方式结合了懒汉式和饿汉式的优点,线程安全且高效。

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

    // 静态内部类
    private static class SingletonHolder {
        private static final SingletonStaticInnerClass INSTANCE = new SingletonStaticInnerClass();
    }

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

优点

  • 利用了类加载机制,保证线程安全
  • 延迟初始化,按需加载
  • 不需要同步,性能较高

这几种方式都可以实现单例模式,具体使用时可以根据项目的实际需求进行选择。

在 JDK 中,单例模式被广泛应用于很多核心类和工具类中。以下是一些经典的 JDK 类或组件使用单例模式的例子:

jdk中使用到的单例模式

1. java.lang.Runtime

Runtime 类用于与 JVM 交互,并提供了管理和控制 JVM 的方法。它使用了饿汉式单例。

java 复制代码
Runtime runtime = Runtime.getRuntime();
  • 使用场景Runtime 提供了 JVM 相关的全局服务,比如执行操作系统命令、获取可用的内存和处理器数量等。
  • 实现 :通过 getRuntime() 方法获取唯一实例,类加载时就创建实例。
2. java.awt.Desktop

Desktop 类提供了一些平台相关的桌面操作功能,如打开浏览器、邮件客户端等。它也是通过单例模式实现的。

java 复制代码
Desktop desktop = Desktop.getDesktop();
  • 使用场景:用于与本地操作系统的桌面功能交互,如打开文件、发送邮件等。
  • 实现 :通过 getDesktop() 方法获取唯一实例。
3. java.lang.System

System 类提供了许多静态方法,用于与系统环境交互,如读取环境变量、标准输入输出等。它虽然没有传统意义的 getInstance(),但其设计本质上是一种单例模式,主要通过静态方法提供系统服务。

java 复制代码
System.out.println("Hello, World!");
  • 使用场景:处理标准输入输出流、系统属性、环境变量等。
  • 实现:通过静态方法提供全局访问,不允许实例化。
4. java.util.logging.LogManager

LogManager 类负责管理全局日志配置,确保整个应用程序中日志记录的一致性。

java 复制代码
LogManager logManager = LogManager.getLogManager();
  • 使用场景:控制全局的日志配置,管理所有的 Logger 实例。
  • 实现:使用单例模式确保只有一个日志管理器实例在运行时存在。
5. java.sql.DriverManager

DriverManager 用于管理数据库驱动程序,并处理与数据库的连接请求。

java 复制代码
Connection connection = DriverManager.getConnection(url, user, password);
  • 使用场景:管理数据库连接,加载和注册 JDBC 驱动程序。
  • 实现:通过静态方法管理数据库连接,全局管理驱动程序的加载。
6. java.util.Calendar

Calendar 类用来操作日期和时间的实例,在一些实现(如 GregorianCalendar)中也使用了单例模式。

java 复制代码
Calendar calendar = Calendar.getInstance();
  • 使用场景:用于日期和时间的计算与操作。
  • 实现 :通过 getInstance() 提供全局访问点。
7. java.nio.file.FileSystems

FileSystems 类用来管理文件系统的访问。

java 复制代码
FileSystem fileSystem = FileSystems.getDefault();
  • 使用场景:获取文件系统的根路径,处理路径的文件操作。
  • 实现 :通过 getDefault() 方法获取默认的文件系统,内部实现单例模式。

总结

这些 JDK 中的类,采用单例模式的原因通常是:

  • 确保系统中某个类只有一个实例,避免资源浪费。
  • 提供全局访问点,使得这些实例能够被多个地方访问和共享。
  • 方便管理与外部系统交互的资源,如日志管理器、数据库连接、文件系统、JVM 资源等。
相关推荐
.生产的驴几秒前
SpringCloud Gateway网关路由配置 接口统一 登录验证 权限校验 路由属性
java·spring boot·后端·spring·spring cloud·gateway·rabbitmq
MavenTalk5 分钟前
Move开发语言在区块链的开发与应用
开发语言·python·rust·区块链·solidity·move
v'sir14 分钟前
POI word转pdf乱码问题处理
java·spring boot·后端·pdf·word
提高记忆力22 分钟前
SpringBoot整合FreeMarker生成word表格文件
java·spring
JDS_DIJ23 分钟前
RabbitMQ
java·rabbitmq·java-rabbitmq
XiaoLeisj37 分钟前
【JavaEE初阶 — 多线程】生产消费模型 & 阻塞队列
java·开发语言·java-ee
2401_8401922740 分钟前
python基础大杂烩
linux·开发语言·python
@东辰1 小时前
【golang-技巧】- 定时任务 - cron
开发语言·golang·cron
hxj..1 小时前
【设计模式】外观模式
java·设计模式·外观模式
机器人天才一号1 小时前
C#从入门到放弃
开发语言·c#