此页内容

015、实现单例模式

480字约2分钟

2025-03-17

(1)懒汉模式

懒汉模式是指在第一次需要实例时才创建,因为他是懒惰的。需要注意,在多线程情况下需要额外的同步机制才可以保证线程安全;

public class SingletonLazy {
    // 使用volatile关键字确保多线程环境下的可见性和有序性
    private static volatile SingletonLazy instance;

    // 私有构造函数防止外部实例化
    private SingletonLazy() {
        // 防止通过反射机制创建实例(可选)
        if (instance != null) {
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
    }

    // 提供全局访问点,使用双重检查锁定(Double-Checked Locking)来减少同步开销
    public static SingletonLazy getInstance() {
        if (instance == null) { // 第一次检查,无需同步
            synchronized (SingletonLazy.class) { // 同步代码块
                if (instance == null) { // 第二次检查,确保只有一个实例被创建
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

    // 其他方法...
}

(2)饿汉模式

饿汉模式是指在类加载时便创建好实例,因为它是饥饿的。由于类加载是由JVM管理的,所以饿汉模式在多线程环境下是线程安全的,无需额外的同步机制。

public class SingletonEager {
    // 在类加载时就创建实例
    private static final SingletonLazy instance = new SingletonEager();

    // 私有构造函数防止外部实例化
    private SingletonEager() {
        // 防止通过反射机制创建实例(可选)
        if (instance != null) {
            throw new RuntimeException("Use getInstance() method to get the single instance of this class.");
        }
        // 注意:这里的异常抛出实际上在饿汉模式下是多余的,因为instance在类加载时就已经被初始化了。
        // 这段代码主要是为了与懒汉模式保持一致,以展示如何防止反射攻击。
        // 在实际应用中,可以省略这部分代码。
    }

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

    // 其他方法...
}