美文网首页
枚举来实现单例

枚举来实现单例

作者: Drew_MyINTYRE | 来源:发表于2022-06-17 08:42 被阅读0次

双重校验锁 实现单例:

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
} 

枚举 实现单例:

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
} 

上面的双重锁校验的代码很臃肿,是因为大部分代码都是在保证线程安全。为了在保证线程安全和锁粒度之间做权衡,代码难免会写的复杂些。但是,这段代码还是有问题的,因为他无法解决 反序列化会破坏单例 的问题。

那么,为什么使用枚举就不需要解决线程安全问题呢?

其实在 底层 还是做了线程安全方面的保证的。因为虚拟机在加载枚举的类的时候,会使用 ClassLoaderloadClass 方法,而这个方法使用同步代码块保证了线程安全,所以,创建一个 enum 类型是线程安全的。

public enum T {
    SPRING, SUMMER, AUTUMN, WINTER;
}

反编译后代码为:

public final class T extends Enum
{
    ...

    public static final T SPRING;
    public static final T SUMMER;
    public static final T AUTUMN;
    public static final T WINTER;
    private static final T ENUM$VALUES[];
    static
    {
        SPRING = new T("SPRING", 0);
        SUMMER = new T("SUMMER", 1);
        AUTUMN = new T("AUTUMN", 2);
        WINTER = new T("WINTER", 3);
        ENUM$VALUES = (new T[] {
            SPRING, SUMMER, AUTUMN, WINTER
        });
    }
}

枚举可解决反序列化会破坏单例的问题

对于序列化这件事情,为什么枚举又有先天的优势了呢?

在序列化的时候 Java 仅仅是将枚举对象的 name 属性输出到结果中,反序列化的时候则是通过 java.lang.Enum 的 valueOf 方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的,因此禁用了writeObjectreadObjectreadObjectNoDatawriteReplacereadResolve 等方法。

枚举的反序列化并不是通过反射实现的。所以,也就不会发生由于反序列化导致的单例破坏问题。

public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {  
    T result = enumType.enumConstantDirectory().get(name);  
    
    if (result != null)  
        return result;  

    if (name == null)  
        throw new NullPointerException("Name is null");  

    throw new IllegalArgumentException(  
        "No enum const " + enumType +"." + name);  
} 

相关文章

  • 枚举单例

    描述 本文先反编译枚举,再使用枚举实现单例 枚举 单例 单例源码 单例反编译 引用 http://www.benf...

  • <转> 通过枚举 enum 来实现单例模式

    转自:通过枚举 enum 来实现单例模式 枚举 通过enum关键字来实现枚举,在枚举中需要注意的有: 枚举中的属性...

  • 枚举来实现单例

    双重校验锁 实现单例: 枚举 实现单例: 上面的双重锁校验的代码很臃肿,是因为大部分代码都是在保证线程安全。为了在...

  • 单例模式之枚举类enum

    通过枚举实现单例模式 枚举类实现单例模式的优点 对于饿汉式单例模式和懒汉式单例模式了解的同学,使用以上两种单例模式...

  • 单例模式

    饿汉模式: 懒汉模式: Double CheckLock(DCL)实现单例 静态内部类实现单例 枚举单例 使用容器...

  • 枚举单例——避免反序列化破坏单例

    六种单例模式实现 枚举单例 深度解析单例与序列化

  • java单例模式小结

    双检索实现的单例,是线程安全的。 枚举类型实现的单例,目前比较推荐

  • 使用枚举来实现单例

    从jdk1.5开始,可通过编写一个包含单个元素的枚举类型来实现单例: 这种方法在功能上与共有域方法相近,但它更加简...

  • 单例

    使用单例设计模式的类只有一个对象实例,基于此核心来编写代码。 懒汉式 饿汉式 内部静态类实现单例 枚举单例 上述单...

  • Effective Objective-C读后笔记(4)

    31、dispatch_once实现单例 使用dispatch_once实现单例设计模式。 32、多用枚举器,少用...

网友评论

      本文标题:枚举来实现单例

      本文链接:https://www.haomeiwen.com/subject/jxmcvrtx.html