zoukankan      html  css  js  c++  java
  • 设计模式(一)单例模式:2-懒汉模式(Lazy)

    思想:

      相比于饿汉模式,懒汉模式实际中的应用更多,因为在系统中,“被用到时再初始化”是更佳的解决方案。

      设计思想与饿汉模式类似,同样是持有一个自身的引用,只是将 new 的动作延迟到 getinstance() 方法中执行。

    public final class LazySingleton {
    
        private static LazySingleton instance;
    
        private LazySingleton() {
            if (instance != null) {
                throw new IllegalStateException();
            }
        }
    
        public static synchronized LazySingleton getInstance() {
            if (instance == null) {
                instance = new LazySingleton();
            }
            return instance;
        }
    }
    • 反射能否打破单例?

      对于 LazySingleton,这是个很有趣的问题,虽然我们在私有构造器中增加了 instance==null 的判断,但是由于延迟加载的原因,使得它无法完美地规避反射的入侵。

      这涉及到了反射入侵和 getInstance() 方法调用顺序的问题。

      如果在调用 getInstance() 方法之前进行反射入侵,那么就会打破单例,反之,可以保证单例。

    public class LazySingletonTest {
    
        @Test
        public void testReflectSuccess() throws Exception {
            Constructor<?> constructor = LazySingleton1.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            LazySingleton1 singleton1 = (LazySingleton1) constructor.newInstance();
            LazySingleton1 singleton2 = LazySingleton1.getInstance();
            Assert.assertNotSame(singleton1, singleton2);
        }
    
        @Test
        public void testReflectFailure() throws Exception {
            LazySingleton1 singleton1 = LazySingleton1.getInstance();
            Constructor<?> constructor = LazySingleton1.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            try {
                LazySingleton1 singleton2 = (LazySingleton1) constructor.newInstance();
                Assert.fail();
            } catch (Exception e) {
                // Do nothing, test pass
            }
        }
    }
    • 为什么是 synchronized 方法?

      因为是延迟加载,考虑到多线程情况,需要对方法同步。

    • 同步方法带来的性能问题?

      可以使用 synchronized 代码块 + Double-check Locking + volatile 关键字,对 LazySingleton 进行深一步优化,详情见:第003弹:懒汉型单例模式的演变

     
    •  优势?劣势?

      优势:延迟加载。

      劣势:不能完全屏蔽反射入侵,而且代码较为繁琐。

  • 相关阅读:
    Visual Studio Code必备插件
    webpack4+:. css属性自动追加前缀 与 mini-css-extract-plugin 插件 打包冲突问题
    webpack4.x抽取css【extract-text-webpack-plugin与mini-css-extract-plugin】
    javaScript中slice, substring,substr三者区别以及用法扩展
    Spring Boot实践——Mybatis分页插件PageHelper的使用
    Nginx配置详解
    Maven的几个常用plugin
    excel拼接数据宏
    我的Linux之路——windows10用WMware安装CentOS7.5 虚拟机详细步骤
    Spring Boot实践——多线程
  • 原文地址:https://www.cnblogs.com/jing-an-feng-shao/p/7501460.html
Copyright © 2011-2022 走看看