设计模式之【单例模式】

完美的单例

双重检查锁(DCL

用处:延迟初始化,降低同步开销。double checked locking

注意:single必须声明为volatile,且支持JDK1.5及以上版本。

 

对象初始化需要三个步骤:

memory=allocate();     //1.分配内存空间

ctorInstance(memory)   //2.初始化对象

instance=memory       //3.设置对象指向分配的内存

 

如果single不是volatile的话,那么处理器会有可能重排序2 3步骤,导致多线程并发时得到实例已经分配内存空间,但并未初始化。

Volatile保证了单例对象的原子性、可见性,禁止了步骤2 3的重排序。

 

public class Singleton {

 

private volatile static Singleton single;

private Singleton(){

 

}

 

public static Singleton getInstance() {

if(single==null){

synchronized(Singleton.class){

if(single==null){

single=new Single();

}

}

}

return single;

}

}

 

静态内部类单例

好处:JVM在类的初始化阶段(即在Class被加载后,且被线程使用之前),会执行类的初始化。在执行类的初始化期间,JVM会去获取一个锁。这个锁可以同步多个线程对同一个类的初始化。

基于类初始化锁【是类的初始化,并非对象初始化】的特性,可以以静态内部类的方式实现延迟初始化单例:

public class Singleton {

private static class SingletonHolder{

public static Singleton single = new Singleton();

}

 

private Singleton(){

 

}

 

public static Singleton getInstance() {

return SingletonHolder.single;

}

}

 

 

 

初始化一个类,包括执行这个类的静态初始化和初始化这个类中声明的静态字段。根据JAVA规范,当发生如下情况,将初始化一个类:

T是一个类,且T类的一个实例被创建;

T是一个类,且T类中声明的一个静态方法被调用;

T中声明的一个静态字段被赋值;

T中声明的一个静态字段被使用,且这个字段不是一个常量字段;

T是一个顶级类,而且一个断言语句嵌套在T内部被执行。

 

枚举

枚举是天生的单例。

 

posted @ 2017-07-04 17:04  Mr.Ming2  阅读(183)  评论(0编辑  收藏  举报