1:Double Check Lock(DCL)
DCL方式实现单例设计模式既能够在需要的时候初始化单例,又能够保证线程安全,且单例对象调用getInstance不进行同步锁。
public class Singleton
{
private static Singleton mInstance = null;
private Singleton(){
}
public void doSomething(){
System.out.println("do..something")
}
public static Singleton getInstance(){
if(mInstance == null){
synchronized(Singleton.class){
if(mInstance == null){
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
在getInstance方法中对mInstance进行了两次的判空:第一层判断主要是为了避免不必要的同步,第二层的判断是为了在null的情况下创建实例。
DCL的应用使得资源的利用率高,只有第一次执行getInstance时单例对象才会实例化。但是在第一次加载的过程中反应稍慢,由于java内存模型的原因偶尔会失败。
2:静态内部类单例模式
DCL在并发环境比较复杂或是jdk1.6以下可能会出现dcl失效的情况,在《Java并发编程》中提及,可以通过代码进行优化
public class Singleton
{
private Singleton(){
}
public void doSomething(){
System.out.println("do..something")
}
public static Singleton getInstance(){
return SingletonHolder.mInstance;
}
private static class SingletonHolder
{
private static final Singleton mInstance = new Singleton();
}
}
第一调用getInstance方法时,虚拟机会加载内部类SingletonHolder,这样做的优点有:
- 确保线程安全
- 保证单例对象的单一
- 延迟单例的实例化