美文网首页
线程安全单例习题

线程安全单例习题

作者: 抬头挺胸才算活着 | 来源:发表于2020-06-10 21:13 被阅读0次

    习题1

    // 问题1:为什么加 final
    // 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例
    public final class Singleton implements Serializable {
    // 问题3:为什么设置为私有? 是否能防止反射创建新的实例?
      private Singleton() {}
      // 问题4:这样初始化是否能保证单例对象创建时的线程安全?
      private static final Singleton INSTANCE = new Singleton();
      // 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你  知道的理由
      public static Singleton getInstance() {
        return INSTANCE;
      }
      public Object readResolve() {
        return INSTANCE;
      }
    }
    
    1. 怕子类覆盖父类的方法,破坏安全性
    2. 反序列化可能会产生对象,破坏单例,可以覆盖readResolve为return INSTANCE;
    3. 将默认的构造器设置为私有,防止别的类创建对象。不能防止反射创建新的实例。
    4. 类加载阶段加载静态成员变量由JVM保证线程安全
    5. 封装

    习题2

    // 问题1:枚举单例是如何限制实例个数的
    // 问题2:枚举单例在创建时是否有并发问题
    // 问题3:枚举单例能否被反射破坏单例
    // 问题4:枚举单例能否被反序列化破坏单例
    // 问题5:枚举单例属于懒汉式还是饿汉式
    // 问题6:枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做
    enum Singleton {
    INSTANCE;
    }
    
    1. 枚举类实现继承自Enum,每个变量在内部设置为public final static enum
    2. 同上面4
    3. 不能
    4. 不能
    5. 饿汉式

    习题3

    public final class Singleton {
      private Singleton() { }
      private static Singleton INSTANCE = null;
      // 分析这里的线程安全, 并说明有什么缺点
      public static synchronized Singleton getInstance() {
        if( INSTANCE != null ){
        return INSTANCE;
        }
        INSTANCE = new Singleton();
        return INSTANCE;
      }
    }
    

    线程安全但效率低下,锁的范围有点大,每次都要加锁

    习题4

    public final class Singleton {
        private Singleton() { }
        // 问题1:解释为什么要加 volatile ?
        private static volatile Singleton INSTANCE = null;
        // 问题2:对比实现3, 说出这样做的意义
        public static Singleton getInstance() {
            if (INSTANCE != null) {
                return INSTANCE;
            }
            synchronized (Singleton.class) {
                // 问题3:为什么还要在这里加为空判断, 之前不是判断过了吗
                if (INSTANCE != null) { // t2
                    return INSTANCE;
                }
                INSTANCE = new Singleton();
                return INSTANCE;
            }
        }
    }
    

    1、有序性,防止INSTANCE还是没有初始化好就先赋值了,别的线程拿去用了。
    2、效率,不用每次都加锁
    3、可以有多个依次进入到这里来

    问题5

    public final class Singleton {
        private Singleton() { }
        // 问题1:属于懒汉式还是饿汉式
        private static class LazyHolder {
            static final Singleton INSTANCE = new Singleton();
        }
        // 问题2:在创建时是否有并发问题
        public static Singleton getInstance() {
            return LazyHolder.INSTANCE;
        }
    }
    

    只有调用getInstance的时候才会进行加载类

    相关文章

      网友评论

          本文标题:线程安全单例习题

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