美文网首页IT好文收集java技术文
java单例的四种实现方式

java单例的四种实现方式

作者: 郑知源 | 来源:发表于2016-03-26 20:41 被阅读768次

    单例的四种实现方式

    一、饿汉方式

    public class Singleton{
    
      private static Singleton instance = new Singleton();
    
      private Singleton(){}
    
      public static Singleton getInstance() {
        return instance;
      }
    }
    
    • 优点:代码简单,避免多线程同步问题
    • 缺点:类的初始化阶段就会导致实例化,无法延迟实例化。
    触发类进行初始化条件
    1. 使用new关键字创建一个对象
    2. 读取/设置一个类的静态字段
    3. 使用反射调用类
    4. 初始化一个类时候,如果其父类还未被初始化,会优先触发其父类初始化
    5. 当jvm启动时,用于指定执行的主类

    二、懒汉方式(DCL)

    public class Singleton {
    
        private static volatile Singleton singleton = null;
    
        private Singleton(){}
    
        public static Singleton getSingleton(){
          if(singleton == null){
            synchronized (Singleton.class){
              if(singleton == null){
                singleton = new Singleton();
              }
            }
          }
        return singleton;
       }
    }
    
    • 优点:延迟单例实例化,以DCL方式提高线程并发效率
    • 注意:JDK1.5引入关键字volatile才能达到正常单例效果。对一个volatile域的写,happens- before 于任意后续对这个volatile域的读,即保证了读写操作不会乱序。

    参考文献:
    http://www.race604.com/java-double-checked-singleton/?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io


    三、静态内部类

    public class Singleton {
    
      /**
      * 是静态内部类,该内部类的实例与外部类的实例没有绑定关系,
      * 而且只有被调用到才会装载,从而实现了延迟加载
      */
      private static class SingletonHolder {
        //保证了线程安全
        private static final Singleton INSTANCE = new Singleton();
    }
    
      private Singleton (){}
      
      public static final Singleton getInstance() {    
          return SingletonHolder.INSTANCE;
      }
    }
    
    • 优点1:线程安全——利用了classloader机制保证只有一个线程来初始化类。
    • 优点2:延迟实例化——只有通过getInstance方法才会触发内部类被初始化。

    四、枚举

    public enum Singleton {
    
      INSTANCE;
    
      private String name;
    
      public String getName(){
        return name;
      }
    
      public void setName(String name){
        this.name = name;
      }
    }
    

    在JDK1.5加入enum特性

    使用enum实现单例优点:
    1. 线程安全(构造方法)——无序担心DCL带来的影响
    2. 不因为序列化而产生新实例
    3. 防止反射攻击

    参考文献:
    https://segmentfault.com/q/1010000000646806

    相关文章

      网友评论

      • 1c63df731bad:谢谢分享
      • SteveGuRen:不错,今日是第一次看到枚举方法可以实现单例
      • 锄小杨:1.8 好像有新的写法。对eumu 一直不太了解
        郑知源:@我叫锄头
        enum特性:
        1 构造方法不支持public/protected,而且创建实例时是线程安全的。构造方法只是在构造枚举值的时候被调用。
        2 实际上enum是final类,不可继承——编译器将enum类型单独编译成了一个字节码文件。
        3 枚举值都是public static final。
        4 调用Singleton.INSTANCE才会被实例化。
      • c3fb30304c60:喜欢
        郑知源: @拥有一双魔力手 谢谢支持

      本文标题:java单例的四种实现方式

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