简介: 单例模式是很是经典的高频面试题,文章主要阐述单例模式的应用场景、IDEA 环境下的多线程调试方式、保证线程安全的单例模式策略、反射暴力攻击单例解决方案及原理分析、序列化破坏单例的原理及解决方案、常见的单例模式写法等方面来全面的解析单列模式的细节。java
单例模式主要包含如下几种写法:面试
饿汉式单例是在类加载时候就马上初始化,而且建立单例对象,有着绝对的线程安全性,由于在线程还未出现以前就已经被建立了,因此不存在访问线程安全性 数据库
优势:安全
缺点:微信
代码实现:多线程
public class HungrySingleton { private HungrySingleton(){ } private static HungrySingleton hungrySingleton = new HungrySingleton(); public static HungrySingleton getHungrySingleton() { return hungrySingleton; } }
咱们也能够采用静态代码块来实现:框架
public class HungryStaticSingleton { private static final HungryStaticSingleton hungryStaticSingleton; static { hungryStaticSingleton = new HungryStaticSingleton(); } private HungryStaticSingleton(){ } public static HungryStaticSingleton getHungryStaticSingleton() { return hungryStaticSingleton; } }
上述两种写法都很是简单,饿汉式适用的场景通常是单例对象比较少的状况,在这基础上咱们下面看一下性能更优的写法。
被外部类调用的时候内部类才会加载,会出现线程安全问题 性能
代码实现: 测试
实现单例类 LazySimpleSingleton
:编码
public class LazySimpleSingleton { private LazySimpleSingleton(){} private static LazySimpleSingleton lazySimpleSingleton = null; public static LazySimpleSingleton getLazySimpleSingleton() { if (lazySimpleSingleton == null){ lazySimpleSingleton = new LazySimpleSingleton(); } return lazySimpleSingleton; } }
咱们编写线程测试类:
public class LazySimpleSingletonTest { public static void main(String[] args) { new Thread(()->{ LazySimpleSingleton lazySimpleSingleton = LazySimpleSingleton.getLazySimpleSingleton(); System.out.println(lazySimpleSingleton); }).start(); new Thread(()->{ LazySimpleSingleton lazySimpleSingleton = LazySimpleSingleton.getLazySimpleSingleton(); System.out.println(lazySimpleSingleton); }).start(); } }
正常状况下输出的两个对象是相同的,也是单例, 可是会存在输出不一样的状况,也就是说出现线程安全问题,这里咱们用 IDEA
的调试功能来进一步的详细看看各个线程的执行状况
用线程模式调试,手动控制线程的执行顺序来跟踪内存的变化状态。先给线程内容打上断点:
本文由AnonyStar 发布,可转载但需声明原文出处。
仰慕「优雅编码的艺术」 坚信熟能生巧,努力改变人生
欢迎关注微信公帐号 :coder简码 获取更多优质文章
更多文章关注笔者博客 : IT简码