定义: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;
}
}
}
总结:枚举类型不允许被继承,同样是线程安全的且只能被实例化一次