美文网首页
单例模式最佳实践

单例模式最佳实践

作者: YyangSir | 来源:发表于2019-04-29 23:41 被阅读0次

    简单介绍

    单例模式是最简单的设计模式之一,提供了一种创建对象的方式,确保在整个系统中只有一个对象被创建.单例模式解决了频繁创建重复对象的问题节约资源,可以省略创建对象所需要花费的时间,对于一些重量级对象而言这点是很重要的.并且因为不需要频繁创建对象 GC 的压力也会有所减轻.

    单例模式的一些实现方式

    通常来说在 Java 中的单例模式分为饿汉式和懒汉式,而且单例类需要一个 private 的构造函数防止被其他代码实例化.下面来具体说一下java 中单例模式的实现.

    饿汉式

    public class Singleton{
        private static Singleton instance =new Singleton();
        //私有化构造方法
        private Singleton(){}
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    饿汉式的单例模式代码简单,线程安全,通过classLoader机制保证了单例对象的唯一性 但是不能确保instance 是在调用getInstance()方法的时候生成的不能达到懒加载效果

    懒汉式

    public class Singleton{
        private static Singleton instance;
        private Singleton(){}
        //加入 synchronize 保证线程安全
        public synchronized static Singleton getInstance(){
            if(instance==null){
                instance=new Singleton();
            }
            return instance;
        }
    }
    

    在获取的时候创建实例可以达到延迟加载的效果并且加入了 synchronize 保证线程安全,但每次调用代码的时候都要加锁,性能比较低还有可能发生阻塞

    DCL双重校验锁

    public class Singleton{
        //volatile防止指令重排序
        private static volatile Singleton instance=null;
        
        private Singleton(){}
        
        public static Singleton getInstance(){
            if(instance==null){
                synchronized(Singleton.class){
                    //加入第二次校验
                    if(instance==null){
                        instance=new Singleton();
                    }
                }
            } 
            return instance;
        }
    }
    

    双重校验锁就是为了解决上述问题而存在的,先检查实例是否存在然后再去创建,可以不用每次调用方法都获取同步锁性能会有一些提升,减小的锁的颗粒度.但是 java 对象的创建和赋值不是一步操作的,有可能先去赋值给中instance之后才去创建 Singleton 这时添加volatile关键字防止指令重排序解决了这个问题.

    静态内部类

    public class Singleton{
        private Singleton(){}
        public static class SingleHoler{
            public static final Singleton instance=new Singleton();
        }
        public static Singleton getInstance(){
            return SingleHoler.instance;
        }
    }
    

    使用静态内部类时,当Singleton被创建的时候不会去加载SingleHoler,只有第一次调用getInstance()方法时才回去创建instance,加载SingleHoler将常量池中的符号引用替换成直接引用,这种方式不仅保证了线程安全而且可以达到延迟加载的效果.

    最佳实践

    public enum Singleton{
        INSTANCE;
        public void print(){
            System.out.println("快乐就完事了!");
        }
    }
    

    这种方法在功能上与公有域方法相近,但是它更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法。 --《Effective Java 中文版 第二版》

    简单到不能再简单了啊.jvm 在加载枚举类的时候会使用loadClass方法使用同步代码块解决线程安全问题.使用 enum 的单例模式还能避免反序列化破坏单例并且不能被反射攻击.

    相关文章

      网友评论

          本文标题:单例模式最佳实践

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