菜鸟笔记
提升您的技术认知

单例模式的六种写法

单例模式的六种写法

重新回顾一下设计模式中的单例模式。
单例模式就是保证一个类只有一个实例,并提供一个访问它的全局访问点。使用场景:

  • 整个项目需要一个共享访问点或共享数据。
  • 创建一个对象需要耗费的资源过多,比如访问I/O或者数据库等资源。
  • 工具类对象。

单例模式有很多种写法,最常见有六种写法。
1.饿汉式

public class Singleton {
  
    //饿汉式
    private Singleton(){
  }
    private static Singleton instance = new Singleton();
    public static Singleton getInstance(){
  
        return instance;
    }
}

优点:取对象的速度快;避免了多线程同步问题。
缺点:因为在类加载时就已经初始化,所以类加载较慢;容易造成内存浪费。

2.懒汉式(线程不安全)

public class Singleton {
  
    //懒汉式(线程不安全)
    private Singleton(){
  }
    private static Singleton instance;
    public static Singleton getInstance(){
  
        if (instance == null) {
  
            instance = new Singleton();
        }
        return instance;
    }
}

优点:在第一次调用时才会初始化,不会造成内存浪费。
缺点:获取对象速度较慢;多线程是不安全;

3.懒汉式(线程安全

public class Singleton {
  
    //懒汉式(线程安全)
    private Singleton(){
  }
    private static Singleton instance;
    public static synchronized Singleton getInstance(){
  
        if (instance == null) {
  
            instance = new Singleton();
        }
        return instance;
    }
}

优点:线程安全;不会造成内存浪费;
缺点:每次调用方法getInstance()时都要进行同步,造成不必要的开销。

4.双重检查模式(DCL)

public class Singleton {
  
    private Singleton(){
  }
    private static volatile Singleton instance;
    public static Singleton getInstance(){
  
        if (instance == null) {
  
            synchronized (Singleton.class){
  
                if (instance == null) {
  
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

优点:只有第一次获取对象是才会进行同步,资源利用高;
缺点:第一次加载是较慢;高并发环境会存在DCL失效问题;

5.静态内部类模式

public class Singleton {
  
    private Singleton(){
  }
    private static class SingletonHodler{
  
        private static final Singleton instance = new Singleton();
    }
    public static Singleton getInstance(){
  
        return SingletonHodler.instance;
    }
}

优点:第一次调用getInstance()方法时才会加载类SingletonHodler并初始化Singleton 对象,既确保线程安全,又保证Singleton类的唯一性。所以写单例模式时推荐使用这种模式。

6.枚举

public enum  Singleton {
  
    INSTANCE;
    public void todo(){
  
        
    }
}

优点:简单;线程安全。
缺点:代码可读性低。

总结以上6种单例模式的写法,推荐使用静态内部类单例模式。