美文网首页
单例的几种安全实现方法及几个问题

单例的几种安全实现方法及几个问题

作者: entro | 来源:发表于2019-01-31 21:30 被阅读0次

线程安全的可用单例模式的几种实现

1.通过static final 实现的饿汉单例

只要编译器一看到该类就会初始化单例,无法达到 延迟加载的目的。

    class Singleton{
        private static final Singleton instance = new Singleton();

        public static Singleton getInstance() {
            return instance;
        }
    }
2.借助静态内部类、static实现的懒汉单例

外部类的静态成员类与外部类没有绑定关系,只有被调用才会加载,从而实现了懒加载。

    class Singleton{    
        private static class SingletonHolder {
            private static final Singleton SINGLETON = new Singleton();
        }
    
        public static Singleton getInstance() {
           return SingletonHolder.SINGLETON;
        }
    }
    
3.双重校验单例模式

加入volatile防止指令重排导致的未完全实例的异常

class Singleton{
    private volatile static Singleton singleton;
           
    public static Singleton getInstance(){       

        if(singleton == null){                      
            synchronized(Singleton.class){          
                if(singleton == null){              
                    singleton = new Singleton();    
                }
            }
        } 
        
        return singleton;           
    }
}
4.枚举单例

把需要单例功能直接定义到一个单枚举中,此方法是《effectJava》推荐的方法
可以做到懒加载,并防止反射(序列化)、反序列化破坏单例

public enum Singleton{
    SINGLETON;
    
}
注意的地方

出了内部类单例和枚举单例外的几种没有对反射(序列化会通过反射调用无参数的构造方法创建一个新的对象。)、反序列化 进行防护,需要在类的内部加入两种防护

    // 序列化会通过反射调用无参数的构造方法创建一个新的对象。
    Singleton(){// 这里防止反射破坏单例
        if(singleton !=null) {
            throw  new RuntimeException("cannot create another instance!");
        }
    }

    //防止反序列化获取多个对象的漏洞
    //无论是实现Serializable接口,或是Externalizable接口,当从I/O流中读取对象时,readResolve()方法都会被调用到。
    private Object readResolve(){
        return singleton;
    }
问题:
    1. 枚举是什么时候加载的,枚举单例有没有懒加载?
    • 枚举是调用的时候加载的,符合懒加载
    1. 序列化和反序列化为什么都要防护,如果防护了序列化就不存反序列化的问题了?
    • 多重防护,意义不是特别大(这里不是很确定)
    1. 序列化是否必须要继承序列化接口,不继承可以序列化么。
    • 不继承序列化也可以序列化。例如在一些监控或者框架里动态修改字节码。
      AOP的无接口类代理就是动态修改字节码。

相关文章

网友评论

      本文标题:单例的几种安全实现方法及几个问题

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