创建型模式

单例模式

image.png

饿汉式

  1. // 问题1:为什么加 final
  2. // 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例:readResolve()方法
  3. public final class Singleton implements Serializable {
  4. // 问题3:为什么设置为私有? 是否能防止反射创建新的实例?
  5. private Singleton() {}
  6. // 问题4:这样初始化是否能保证单例对象创建时的线程安全?
  7. private static final Singleton INSTANCE = new Singleton();
  8. // 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你知道的理由
  9. public static Singleton getInstance() {
  10. return INSTANCE;
  11. }
  12. public Object readResolve() {
  13. return INSTANCE;
  14. }
  15. }

低性能 懒汉式

  1. public final class Singleton {
  2. private Singleton() { }
  3. private static Singleton INSTANCE = null;
  4. // 分析这里的线程安全, 并说明有什么缺点 ==> 无论如何,都得等待所释放
  5. public static synchronized Singleton getInstance() {
  6. if( INSTANCE != null ){
  7. return INSTANCE;
  8. }
  9. INSTANCE = new Singleton();
  10. return INSTANCE;
  11. }
  12. }

DCL 优化 懒汉式

什么是双重检查锁:
双重检查锁是一个对单例模式的优化,具体做了如下步骤:

  1. 在synchronized外边,做了一个空判断,好处如下:

    1. (相对于直接synchronized)避免用户态到内核态的一个消耗,即不用等锁释放,进行上下文切换
  2. new 对象的时候需要经过如下步骤:

    1. 分配内存空间
    2. 对象初始化
    3. instance 指针指向内存空间
  3. 不使用 volitale修饰的话,可能会出现一个指令重排,会导致如下结果

    1. 如果先执行 instance 指针指向内存空间:

A线程刚执行到new对象,B线程刚判断实例是否为空(即synchronized方法前).
B线程此时拿到的是没有初始化的结果(只分配了空间,还没有调用构造方法,拿到了个半成品)

  1. 为什么加volitale能拿到一个正常的结果:
    1. volitale只能保证单个JVM指令的原子性和可见性
    2. 真正的作用:
      1. 在 new 对象前边添加 store store屏障
      2. 在 new 对象后边添加 store load 屏障
      3. 最终保证 new 对象的过程,对外不可乱序获取,因此保证了线程安全性
  1. public final class Singleton {
  2. private Singleton() { }
  3. // 问题1:解释为什么要加 volatile ?
  4. //==>避免重排序后,拿到的引用,只是分配了内存空间,但是没有来得及调用构造方法!
  5. private static volatile Singleton INSTANCE = null;
  6. // 问题2:对比实现3, 说出这样做的意义
  7. // ==> 创建好后,大家都直接用就行了,不像未优化的版本,就算已经创建了,也得等待锁
  8. public static Singleton getInstance() {
  9. if (INSTANCE != null) return INSTANCE;
  10. synchronized (Singleton.class) {
  11. // 问题3:为什么还要在这里加为空判断, 之前不是判断过了吗
  12. //==>若无:t1 t2都判断外面的实例为null,t1拿到锁创建实例后,t2又进来创建一个.
  13. if (INSTANCE != null) { // t2
  14. return INSTANCE;
  15. }
  16. INSTANCE = new Singleton();
  17. return INSTANCE;
  18. }
  19. }
  20. }

静态内部类 懒汉式

  1. public final class Singleton {
  2. private Singleton() { }
  3. // 问题1:属于懒汉式还是饿汉式(懒汉式,类的创建是懒汉式,第一次加载类时,才会初始化)
  4. private static class LazyHolder {
  5. static final Singleton INSTANCE = new Singleton();
  6. }
  7. // 问题2:在创建时是否有并发问题(JVM负责的类加载是能够保证线程安全的)
  8. public static Singleton getInstance() {
  9. return LazyHolder.INSTANCE; //在这类调用类
  10. }
  11. }

工厂方法模式

建造者模式

结构型模式

适配器模式

代理模式

装饰者模式

单线程线程池返回值使用装饰器模式进行了包装
image.png

行为型模式

迭代器模式

模板方法模式

策略模式:线程池拒绝策略

观察者模式