1. 什么是单例模式?

单例模式(Singleton Pattern)是 Java 设计模式中最常用的一种,它确保一个类只有一个实例,并提供一个全局访问点。这种模式主要用于控制资源访问、配置管理、线程池、缓存等场景。

2. 为什么需要单例模式?

  • 节省资源:避免频繁创建和销毁对象,减少系统开销。
  • 全局访问:提供一个统一的访问入口,方便管理。
  • 数据一致性:确保所有操作都基于同一个实例,避免数据不一致。
  • 线程安全:在多线程环境下,确保实例的唯一性。

3. 单例模式的实现方式

3.1 饿汉式(Eager Initialization)

public class EagerSingleton {
    // 类加载时就创建实例
    private static final EagerSingleton instance = new EagerSingleton();
    
    // 私有构造方法,防止外部实例化
    private EagerSingleton() {}
    
    // 提供全局访问点
    public static EagerSingleton getInstance() {
        return instance;
    }
}

优点:实现简单,线程安全。
缺点:类加载时就初始化,可能造成资源浪费。

3.2 懒汉式(Lazy Initialization)

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

优点:延迟加载,节省资源。
缺点:每次获取实例都要同步,性能较差。

3.3 双重检查锁(Double-Checked Locking)

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

优点:线程安全,延迟加载,性能较好。
缺点:实现稍复杂,需要 volatile 关键字防止指令重排序。

3.4 静态内部类(Static Inner Class)

public class InnerClassSingleton {
    private InnerClassSingleton() {}
    
    private static class SingletonHolder {
        private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
    }
    
    public static InnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

优点:线程安全,延迟加载,实现简洁。
缺点:无法传递参数。

3.5 枚举(Enum)

public enum EnumSingleton {
    INSTANCE;
    
    public void doSomething() {
        // 业务方法
    }
}

优点:线程安全,防止反射攻击,防止反序列化重新创建对象。
缺点:不够灵活,无法继承。

4. 单例模式的应用场景

  • 配置管理类:读取配置文件,全局共享配置信息。
  • 数据库连接池:管理数据库连接,避免频繁创建连接。
  • 日志记录器:统一记录系统日志。
  • 线程池:管理线程资源。
  • 缓存系统:如 Redis 客户端连接。

5. 单例模式的注意事项

  • 线程安全:多线程环境下必须保证实例创建的唯一性。
  • 序列化与反序列化:需要实现 readResolve() 方法防止反序列化创建新实例。
  • 反射攻击:通过反射可以调用私有构造方法,枚举方式可以防止这种攻击。
  • 类加载器:不同的类加载器可能加载出多个单例实例。
  • 性能考虑:根据实际需求选择合适的实现方式。

6. 总结

单例模式是 Java 开发中非常重要的设计模式,掌握其各种实现方式及适用场景对于编写高质量代码至关重要。在实际开发中,推荐使用静态内部类枚举方式实现单例,它们既能保证线程安全,又具有较好的性能。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐