如何在 Java 中实现单例模式

在 Java 中实现单例模式有几种常见的方式,下面是几种典型实现:

1. 饿汉式(Eager Initialization)

这种方式的特点是,单例实例在类加载时就会被创建。

public class Singleton {
    // 1. 创建静态实例
    private static final Singleton INSTANCE = new Singleton();

    // 2. 私有构造方法,防止外部实例化
    private Singleton() {}

    // 3. 提供公共的访问方法
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

特点:

  • 简单易懂,线程安全。
  • 无论是否使用该单例,类加载时都会创建实例。

2. 懒汉式(Lazy Initialization)

单例实例在首次使用时才创建。需要保证线程安全。

public class Singleton {
    // 1. 声明单例实例,延迟初始化
    private static Singleton instance;

    // 2. 私有构造方法,防止外部实例化
    private Singleton() {}

    // 3. 提供公共的访问方法,使用同步控制线程安全
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

特点:

  • 延迟加载,只有在需要时才会创建实例。
  • 线程安全,但每次访问时都要进行同步,性能相对较低。

3. 双重检查锁(Double-Checked Locking)

为了优化性能,可以使用双重检查锁定(DCL)模式,只有在实例为空时才会加锁,避免了每次调用时都加锁的性能问题。

public class Singleton {
    // 1. 声明单例实例,使用 volatile 保证内存可见性
    private static volatile Singleton instance;

    // 2. 私有构造方法,防止外部实例化
    private Singleton() {}

    // 3. 提供公共的访问方法,进行双重检查锁定
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

特点:

  • 线程安全且性能较好。
  • 需要使用 volatile 关键字,保证对 instance 的写入是有序的。

4. 静态内部类(Bill Pugh Singleton)

这种方法通过静态内部类的加载来实现延迟加载,并且线程安全。它是实现单例模式的最佳方式之一。

public class Singleton {
    // 1. 私有构造方法,防止外部实例化
    private Singleton() {}

    // 2. 静态内部类,只有在调用时才会加载
    private static class SingletonHelper {
        // 3. 静态实例,实例在类加载时创建
        private static final Singleton INSTANCE = new Singleton();
    }

    // 4. 提供公共的访问方法
    public static Singleton getInstance() {
        return SingletonHelper.INSTANCE;
    }
}

特点:

  • 延迟加载,且线程安全。
  • 通过静态内部类加载机制,只有在第一次调用 getInstance() 时,SingletonHelper 类才会被加载,保证了懒加载的效果。

5. 枚举式(Enum Singleton)

Java 中枚举类型的单例实现是最简洁且安全的,Java 会确保枚举实例的唯一性和线程安全。

public enum Singleton {
    INSTANCE;

    // 1. 可以添加方法和字段
    public void doSomething() {
        // 业务逻辑
    }
}

特点:

  • 最简洁的实现方式,确保了单例的线程安全。
  • 不允许使用反射来破坏单例,推荐使用这种方式。

总结:

  • 如果不需要延迟初始化,可以使用饿汉式单例。
  • 如果需要延迟初始化且关注性能,可以使用双重检查锁。
  • 如果追求代码简洁且安全,可以使用枚举式单例。
#全栈开发 分享于 2025-01-09
【 内容由 AI 共享,不代表本站观点,请谨慎参考 】