Java单例模式实现:七种写法解析

需积分: 15 1 下载量 76 浏览量 更新于2024-09-07 收藏 177KB PDF 举报
"单例模式是设计模式中的一种,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。在Java中,实现单例模式有多种方式,每种方式都有其特点和适用场景。以下是对单例模式七种写法的详细解释: 1. **懒汉式(线程不安全)**: 这是最简单的实现,只有在第一次调用`getInstance()`方法时才会创建实例。但这种方式在多线程环境下存在竞态条件,可能导致多个线程各自创建一个实例,不符合单例模式的要求。 2. **懒汉式(线程安全)**: 通过在`getInstance()`方法上添加`synchronized`关键字,解决了线程安全问题,确保同一时刻只有一个线程可以执行创建实例的代码。但这样会降低性能,因为每次调用`getInstance()`都需要进行同步,即使实例已经创建完成。 3. **饿汉式**: 在类加载时就创建了单例实例,因此是线程安全的。但这种方式不满足懒加载,即无论何时何地,只要类被加载就会创建实例,可能导致不必要的内存消耗。 4. **饿汉式(变种)**: 使用`static final`字段存储实例,这种方式同样在类加载时创建实例,且由于`final`修饰,无法被改变,确保了线程安全。与第三种方式相比,这种方式更接近于常量,但依然不支持懒加载。 5. **双检锁/双重检查锁定(DCL,Double-Check Locking)**: Java代码: ``` public class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } } ``` 这种方式结合了前两种方法的优点,既实现了懒加载,又保证了线程安全。在`instance`未创建之前,线程进入同步块,确保了实例创建过程中不会被其他线程干扰。`volatile`关键字保证了多线程环境下`instance`变量的可见性,避免了指令重排序的问题。 6. **静态内部类**: ``` public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } ``` 这种方式利用了Java类加载机制,保证了线程安全且实现了延迟加载。静态内部类只有在被首次引用时才会加载,因此`INSTANCE`实例的创建也是延迟的。 7. **枚举**: ``` public enum Singleton { INSTANCE; public void whateverMethod() { } } ``` 通过枚举方式实现单例,既简单又安全,还能防止反射和序列化攻击。这是推荐的最佳实践,因为它既满足了单例的所有需求,又具有良好的编码习惯。 以上七种方式在不同的场景下各有优势,选择哪种方式取决于具体的需求,如是否需要懒加载、对性能的要求、以及是否考虑反序列化或反射攻击等因素。在实际开发中,通常会选择DCL或者枚举方式,因为他们既保证了线程安全,又能实现延迟加载,同时也避免了反射和序列化的问题。