JAVA 设计模式之老生常谈的单例模式

891 阅读3分钟
原文链接: www.jianshu.com

类型:它是一种创建类模式。
在平时开发的时候,无论是自己写还是看别人的代码,可能随时都会看到单例模式。可能有的人都写得不爱了。但是我还是想根据我的见解来说说它。
单例模式就是确保一个类只有一个实例,并提供一个访问它的全局访问点。单例模式写法有好几种。

  • 饿汉式:private static Singleton uniqueInstance = new Singleton();
  • 懒汉式: private static Singleton uniqueInstance = null;

Java里面实现的单例是一个虚拟机的范围。因为装载类的功能是虚拟机的,所以一个虚拟机在通过自己的ClassLoader装载饿汉式实现单例类的时候就会创建一个类的实例。
懒汉式单例有延迟加载和缓存的思想。

懒汉式单例

//懒汉式单例类.在第一次调用的时候实例化自己   
public class Singleton {  
    private Singleton() {}  
    private static Singleton single=null;  
    //静态工厂方法   
    public static Singleton getInstance() {  
         if (single == null) {    
             single = new Singleton();  
         }    
        return single;  
    }  
}

饿汉式单例

//饿汉式单例类.在类初始化时,已经自行实例化   
public class Singleton1 {  
    private Singleton1() {}  
    private static final Singleton1 single = new Singleton1();  
    //静态工厂方法   
    public static Singleton1 getInstance() {  
        return single;  
    }  
}

饿汉式与懒汉式的区别

  • 懒汉式是典型的时间换空间,饿汉式是典型的空间换时间
  • 不加同步的懒汉式是线程不安全的。比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,就可能导致并发问题。饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。

如何保证懒汉式的同步问题

  • 1.同步方法
    public static synchronized Singleton getInstance() {  
           if (single == null) {    
               single = new Singleton();  
           }    
          return single;  
    }
    但这样会降低整个访问的速度,而且每次都要判断。可以用双重检查加锁。
  • 2.双重检查加锁
    双重加锁机制,指的是:并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块后,再次检查实例是否存在,如果不存在,就在同步的情况下创建一个实例。这是第二重检查。
    双重加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。

    public class Singleton {
    
      /**
       * 对保存实例的变量添加volitile的修饰
       */
      private volatile static Singleton instance = null;
      private Singleton(){
    
      }
      public static Singleton getInstance(){
          if(instance == null){
              synchronized (Singleton.class) {
                  instance = new Singleton();
              }
          }
          return instance;
      }
    }

    单元素的枚举类型实现单例

    根据《Effective Java第二版》中的说法,单元素的枚举类型已经成为实现Singleton的最佳方法。

    public enum Singleton  {   
    singleton; 
     private Singleton () {    }
    }

    如有不妥,欢迎指出。哈哈哈哈