在Java1.5以后的版本中volatile修饰符具有禁止指令重排序优化的特性,也是说在 volatile 变量的赋值操作后面会有一个内存屏障(生成的汇编代码上),读操作不会被重排序到内存屏障之前。比如上面的例子,取操作必须在执行完 ①-②-③ 或者 ①-③-② 之后,不存在执行到 ①-③ 然后取到值的情况。从「先行发生原则」的角度理解的话,是对于一个 volatile 变量的写操作都先行发生于后面对这个变量的读操作(这里的“后面”是时间上的先后顺序)。
  静态内部类实现单例
public class Singleton{
private Singleton() {}
private static class SingletonHolder{
private static Singleton instance=new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
  通过在类中创建一个静态内部类来实现单例模式也是利用了JVM的类加载机制保证只创建一份实例,同时与饿汉式单例一样具有线程安全性,而且客户在获取这个单例类实例的时候不会进行同步,没有性能缺陷,也不依赖 JDK 版本。静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时调getInstance()方法,才会装载SingletonHolder类实例化Singleton,这样实现了单例类的懒加载。
  由于使用静态内部类实现单例避免了线程不安全的问题,并且有较高的访问效率以及实现了延迟加载,这种方式是值得推荐的单例实现方式,当然这种方式与饿汉式单例一样不能传入参数。
  枚举实现单例
public enum Singleton {
INSTANCE;
private Singleton() {}
public void method() {
}
}
  从Java1.5版本起,创建单例可以使用简洁的枚举类型。我们直接通过Singleton.INSTANCE来访问实例,创建枚举默认是线程安全的,所以不需要考虑double checked locking,而且枚举还能防止反序列化或者反射攻击导致创建新的实例。《Effective Java》中更是说明单元素的枚举类型已经成为实现Singleton的佳方法。
  单例模式小结
  单例模式是类结构和模式思想简单的一种设计模式,也是实际项目在被使用多的一种模式,Android SDK的许多类以及许多第三方开源库都提供了很多有单例行为的类。单例模式的实现方式有多种,但在实际使用时需要认真考量单例类的线程安全性、访问效率和懒加载属性,所有的限制和设计都要保证Singleton类仅仅被实例化一次。