授课语音

单例模式(Singleton Pattern)

单例模式是一种常用的设计模式,确保一个类只有一个实例,并提供一个全局访问点来获取该实例。该模式可以用于共享资源或避免多个实例引起的性能浪费和数据不一致性。


1. 单例模式的实现方式

单例模式有多种实现方式,常见的有懒汉式、饿汉式以及双重检查锁(DCL)。每种实现方式在不同的使用场景下有不同的优缺点。

1.1 饿汉式单例(Eager Singleton)

在饿汉式单例模式中,类的实例在类加载时就会创建,无论这个实例是否被使用。它的优点是实现简单,线程安全;缺点是如果实例未被使用,仍然会浪费资源。

代码实现

public class Singleton {
    // 类加载时就创建实例,确保只有一个实例
    private static final Singleton instance = new Singleton();

    // 私有构造函数,防止外部直接创建对象
    private Singleton() {}

    // 提供一个全局访问点
    public static Singleton getInstance() {
        return instance;
    }
}

中文注释说明:

  • instance 在类加载时初始化,因此实例是唯一的。
  • getInstance() 方法提供全局访问点,直接返回实例。

1.2 懒汉式单例(Lazy Singleton)

懒汉式单例模式在需要使用实例时才创建实例,因此它是延迟初始化的。懒汉式模式的主要问题是线程安全问题,必须在多线程环境下小心使用。

代码实现

public class Singleton {
    // 只定义了一个实例,但是没有立即创建
    private static Singleton instance;

    // 私有构造函数,防止外部直接创建对象
    private Singleton() {}

    // 提供一个全局访问点,延迟创建实例
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();  // 实例化对象
        }
        return instance;
    }
}

中文注释说明:

  • instance 只有在第一次调用 getInstance() 时才会被初始化。
  • 在多线程环境中,存在多线程同时访问 getInstance() 方法时可能导致多个实例的问题。

1.3 双重检查锁单例(Double-Checked Locking Singleton)

双重检查锁是一种改进懒汉式单例模式的方式,避免了每次调用 getInstance() 时都进行同步检查。它在第一次实例化时加锁,之后无需再加锁,从而提高了性能。

代码实现

public class Singleton {
    // 使用 volatile 保证实例在多线程环境中的可见性
    private static volatile Singleton instance;

    // 私有构造函数,防止外部直接创建对象
    private Singleton() {}

    // 提供一个全局访问点,双重检查锁
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                // 再次检查实例是否为 null,避免多个线程创建多个实例
                if (instance == null) {
                    instance = new Singleton();  // 实例化对象
                }
            }
        }
        return instance;
    }
}

中文注释说明:

  • volatile 关键字确保 instance 在多线程环境中能够及时更新。
  • synchronized 确保在多线程访问时只有一个线程能够创建实例。
  • 双重检查锁的方式确保了只有在第一次创建实例时进行加锁,之后直接返回实例,提高了性能。

2. 各种实现方式的对比

实现方式 优点 缺点
饿汉式 实现简单,线程安全,实例创建即完成 无论是否使用实例,都在加载时创建
懒汉式 延迟创建实例,节省内存 存在线程安全问题
双重检查锁 线程安全且延迟加载,性能较高 实现较为复杂,需要使用 volatile

3. 总结

  • 饿汉式单例:适用于实例创建较早且始终需要的场景。
  • 懒汉式单例:适用于实例创建较晚或不一定每次都需要的场景,但需要注意线程安全问题。
  • 双重检查锁:是一种既能延迟实例化又能保证线程安全的方式,适用于对性能要求较高的场景。

选择适合的实现方式可以有效提高系统的性能和资源利用率。

去1:1私密咨询

系列课程: