单例模式

2020-12-23 11:58:02 浏览数 (1)

定义:Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

饿汉式:线程安全

描述:这种方式比较常用,但容易产生垃圾对象。

优点:没有加锁,执行效率会提高。

缺点:类加载时就初始化,浪费内存。

代码语言:javascript复制
public final class Singleton {  // final不允许被继承

    private static Singleton instance = new Singleton(); // 在定义实例对象时,直接初始化

    private Singleton (){}  // 构造私有化,不允许外部new

    public static Singleton getInstance() {  
       return instance;  
    }  
}  

总结:饿汉式的单例设计模式可以保证多线程下的唯一实例

懒汉式:线程不安全

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。

代码语言:java复制
public final class Singleton {  // final不允许被继承

    private static Singleton instance = null;  
    
    private Singleton (){}  // 构造私有化,不允许外部new
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}  

总结:getInstance在多线程环境下会导致instance被实例化一次以上,并不能保证单利的唯一性

懒汉式:线程安全

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。

优点:第一次调用才初始化,避免内存浪费。

缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

代码语言:javascript复制
public final class Singleton {  

    private static Singleton instance;  
    
    private Singleton (){}  
    
    public static synchronized Singleton getInstance() {  // 加入同步控制,每次只有一个线程进入
       if (instance == null) {  
           instance = new Singleton();  
       }  
       return instance;  
    }  
} 

总结:采用懒汉式 数据同步方式既满足了懒加载又能够100%保证instance实例的唯一性,但是synchronized关键字关键字天生的排他性导致了getInstance方法只能在同一时刻被一个线程所访问,性能低下。

懒汉式:Double-Check

代码语言:javascript复制
public final class Singleton {  

    private volatile static Singleton instance = null; // volatile防止指令重排序
    
    private Singleton (){}  
    
    public static Singleton getInstance() {   
       if (instance == null) {  
          synchronized (Singleton.class) {
             if (instance == null) {
                instance = new Singleton();  
             }
          } 
       }  
       return instance;  
    }  
} 

总结:Double-Check的方式提供了高效的数据同步策略

Holder方式

代码语言:javascript复制
public final class Singleton {

    private Singleton() {}

    // 调用getInstance方法,事实上是获得Holder的instance静态属性
    public static Singleton getInstance() {
        return Holder.instance;
    }

    // 在静态内部类中持有Singleton的实例,并且可被直接初始化
    private static class Holder{
        private static Singleton instance = new Singleton();
    }
}

总结:Holder方式的单例设计模式是最好的设计之一,也是目前使用比较广的设计之一。

枚举方式

代码语言:javascript复制
public final class Singleton {

    private Singleton() {}
    
    public static Singleton getInstance() {

        return EnumHolder.INSTANCE.getSingleton();
    }
    
    private enum  EnumHolder{

        INSTANCE;
        private Singleton instance;
        
        EnumHolder() {
            this.instance = new Singleton();
        }
        
        private Singleton getSingleton(){
            return instance;
        }
    }
}

总结:枚举类型不允许被继承,同样是线程安全的且只能被实例化一次

0 人点赞