单例模式的六种写法
重新回顾一下设计模式中的单例模式。
单例模式就是保证一个类只有一个实例,并提供一个访问它的全局访问点。使用场景:
- 整个项目需要一个共享访问点或共享数据。
- 创建一个对象需要耗费的资源过多,比如访问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种单例模式的写法,推荐使用静态内部类单例模式。