美文网首页
Java单例模式

Java单例模式

作者: arrow_zh | 来源:发表于2021-04-14 10:06 被阅读0次

    单例的5中方式

    1、懒汉式

    缺点:线程不安全

    /**
         * 懒汉式
         * 缺点:线程不安全的
         */
        static class LazyClass {
            private static LazyClass lazyClass = null;
            private LazyClass (){}
    
            public static LazyClass getInstance(){
                if(lazyClass == null) {
                    lazyClass = new LazyClass();
                }
                return lazyClass;
            }
        }
    

    2、懒汉式变种(双重检查加锁)

    /**
         * 懒汉式变种
         * 注意此处的变量必须加volatile修饰 如果不加volatile可能造成线程不安全
         * 主要原因是英文 doubleCheckClass = new DoubleCheckClass() 不是原子操作
         * 其中分为三步,第一步开辟内存空间,第二步初始化对象, 第三步赋值引用,其中在高并发场景下可能发生指重排
         * 双重检查加锁
         */
        static class DoubleCheckClass {
            private static volatile DoubleCheckClass doubleCheckClass = null;
    
            private DoubleCheckClass(){}
    
            public static DoubleCheckClass getInstance(){
                if(doubleCheckClass == null) {
                    synchronized (DoubleCheckClass.class) {
                        doubleCheckClass = new DoubleCheckClass();
                    }
                }
                return doubleCheckClass;
            }
        }
    

    3、饿汉式

    /**
     *饿汉式
    *缺点:一上来就初始化空间,不是用也要占用内存空间
    */
    static class HungryClass {
        private static HungryClasshungryClass= new HungryClass();
    
        private HungryClass(){}
    
        public static HungryClass getInstance(){
            returnhungryClass;
        }
    }
    

    4、静态内部类方式

    /**
         * 静态内部类方式实现
         */
        static class InnerClass {
            private static class  InnerClassHolder {
                /**
                 * 静态类初始化 JVM来保证线程安全
                 */
                private static  InnerClass innerClass = new InnerClass();
            }
    
            private InnerClass(){}
    
            public static InnerClass getInstance(){
                return InnerClassHolder.innerClass;
            }
        }
    

    5、枚举

    /**
     *枚举方式实现单例
    */
    static enum EnumClass {
    instance;
    
    }
    

    破坏单例的三种方式

    1、反射

    解决方案:定义一个全局变量,当第二次创建时候就抛出异常

    2、克隆

    解决方案:重写clone方法,直接返回当前单例对象

    3、序列化

    解决防范:添加readResolve() 返回单例对象

    /**
         * 破坏单例的几种方式
         * 1、反射
         * 2、克隆
         * 3、序列化
         *
         * 解决方法
         * 1、反射
         *    定义一个全局变量,当第二次创建的时候抛出异常
         * 2、克隆
         *   重写clone(),直接返回单例对象
         * 3、序列化
         *    添加readResolve(),返回Object对象
         */
        static class Singleton  implements Serializable,Cloneable{
    
            private static volatile boolean isCreate = false;//默认是第一次创建
            /**
             * 1.构造方法私有化,外部不能new
             */
            private Singleton() {
                if(isCreate) {
                    throw new RuntimeException("已然被实例化一次,不能在实例化");
                }
                isCreate = true;
            }
    
            //2.本类内部创建对象实例
            private static  volatile  Singleton instance;
    
            //3.提供一个公有的静态方法,返回实例对象
            public static  Singleton getInstance() {
                if(instance == null) {
                    synchronized (Singleton.class) {
                        if(instance == null) {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
    
            @Override
            protected Object clone() throws CloneNotSupportedException {
                return instance;
            }
    
            /**
             * 防止序列化破环
             * @return
             */
            private Object readResolve() {
                return instance;
            }
    
        }
    

    相关文章

      网友评论

          本文标题:Java单例模式

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