单例模式有哪些常见的实现方式?

单例模式有多种实现方式,每种方式都有其特点和应用场景。以下是常见的几种实现方式:

  1. 懒汉式(Lazy Initialization)
    • 这种方式支持延迟加载,即单例实例在被客户端首次请求时才创建。
    • 不支持多线程,因为没有加锁操作,所以在多线程环境下不能保证单例的唯一性。
  2. 线程安全的懒汉式
    • 这种方式在懒汉式的基础上增加了同步锁synchronized,使其在多线程中保持单例。
    • 但每次访问getInstance()方法时都要进行线程锁定判断,在高并发环境下会导致系统性能下降。
  3. 饿汉式(Eager Initialization)
    • 在类加载时就创建实例,基于类加载机制,避免了多线程的同步问题。
    • 如果单例类的构造方法中没有包含过多的操作处理,饿汉式其实可以接受。
  4. 双重校验锁(Double-Checked Locking)
    • 这种方式在懒汉式的基础上进行了改进,只有在实例未被创建时才进行同步,这样可以减少大部分的同步开销。
    • 实现复杂,需要特别注意instance需要被声明为volatile,否则可能因为JVM的指令重排导致使用到未完全初始化的实例。
  5. 静态内部类(Static Inner Class)
    • 利用类的加载机制来保证初始化实例时只有一个线程。
    • 静态内部类方式在Singleton类被加载时并不需要立即实例化,而是在需要实例化时,调用getInstance()方法,才会加载StaticHolder类,从而完成Singleton的实例化。
    • 类的静态属性只会在第一次加载类的时候初始化,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
  6. 枚举(Enum)
    • 这是实现单例的最简洁方法,不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
    • 可以通过EasySingleton.INSTANCE.doSomething()的方式调用单例实例的方法。

以下是静态内部类实现单例模式的一个例子:

public class Singleton {
    // 私有构造函数
    private Singleton() {}

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

    // 全局访问点
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public void doSomething() {
        // 实例方法...
    }
}

public class Main {
    public static void main(String[] args) {
        // 通过Singleton类的getInstance方法获取唯一实例
        Singleton singleton = Singleton.getInstance();
        singleton.doSomething();
    }
}

以上就是单例模式的主要实现方式,实际应用时应根据具体情况选择合适的实现方法。

发表评论

后才能评论