先看代码:publicclassSingleton{privateSingleton(){}privatestaticclassSingletonInstance{privatestaticfinalSingletoninstance=newSingleton();}publicstaticSingletongetInstance(){returnSingletonInstance.instance;}}我想应该没有不知道这行个类是干嘛的小伙伴了吧,这是单例模式的一种写法。单例模式是每一个Javaer必须要掌握的设计模式,它所描述的是在某个进程内,某个类有且仅有一个实例。我们知道要破坏单例模式
单例模式确保任何情况下都绝对只有一个补全。像这样的被称为单例模式。创建单例模式的五种方式1.饿汉式publicclassHungry{privatestaticInstanceinstance=newInstance();privateHungry(){}publicstaticInstancegetInstance(){returninstance;}}线程安全实例占用资源多或初始化耗时长,提前初始化实例是一种浪费资源的行为。最好的方法应该是用到的时候再去初始化。如果初始化耗时长,那我们最好不要等到正在要用到它的时候,才去执行这个耗时长的初始化过程,这会影响到系统的性能。2.懒汉式(非线程安
容器单例模式相当于一个容器工具,对外来说只能是一个对象。我们通过map来实现一个单例的容器coding:私有构造方法StringUtils.isNotBlank(key):判断stringkey是不是为空从map容器中获取key线程run方法:在Test这里面会有一个隐患,那就是当两个线程同时进入到map的put中的时候,会出现两个object对象,虽然前面放进去的对象会被后面所覆盖。但是还是一种多线程隐患。ThreadLocal线程单例运行发现,两个线程拿到的不是同一个。ThreadLocal的单例实现模式,主要是针对于同一个线程,在同一个线程中,它所获取的实例都是同一个,但是在不同的线程那
枚举实现单例模式coding:创建一个枚举的EnumInstance类修改Test运行结果,枚举类可以在序列号的情况下实现单例模式现在我们判断一下它的属性是不是在序列化的情况下是不是还是同一个运行结果那我们现在来分析一下它底层是怎么实现的进入到ObjectInputStream类中的readEnum()方法既然系列化不受影响,那反射会不会破坏枚举的单例呢?通过报错信息我们可以知道,枚举类型是无法进行反射的。枚举类的使用
通过反射来破坏单例模式一定要记得将setAccessible()设置为true在私有构造方法中增加一层判断再一次运行:由于反射创建对象,是通过构造函数来进行创建的,所以我们在私有构造方法中,增加一层判断就可以了。对于延迟加载的懒汉式运行之后,和我们预期是一样的但是如何调换加载顺序呢?让反射先执行,然后延迟创建对象后执行的话,结果就是两个不同的对象解决办法,添加一个信号变量运行程序这种方式很好的组织的反射的攻击,但是其实反射对于这种来说也是可以破坏的通过new出来的对象,直接反射修改它的私有信号变量运行结果:这就说明我们通过反射将flag这个信号变量设置成了true了解反射的小伙伴应该是知道的,
单例模式定义:保证一个类仅有一个实例,并提供一个全局访问点。类型:创建型适合场景:想确保任何情况下都绝对只有一个实例优点:在内存中只有一个实例,减少了内存开销可以避免对资源的多重占用设置全局访问点,严格控制访问缺点:没有接口,扩展困难重点:私有构造器线程安全延迟加载序列化和反序列化安全反射coding:懒汉式单例模式创建Test类总结:懒汉式主要是延迟加载,在使用的时候才进行加载操作。懒汉式的问题:在多线程情况下以懒汉式创建对象现在进行多线程debug:设置断点属性为Thread,并且设置为默认debug,现在我们就可以直接切换线程的顺序,使得多线程出现预期的问题选择第一个线程,进入到if判断