Singleton在C++和Java中的运用(二)

2014-11-24 00:38:54 · 作者: · 浏览: 1
反序列化生成的对象都是一个新的对象,打破了Singleton原则。作为补救措施,可以通过将所有成员变量声明为transient,并提供一个readResolve方法。所有成员变量都不参与序列化和反序列化的过程,并且readResolve总是返回一个Singleton对象。实际上这些动作也就表明不再支持序列化。因此最佳选择是不要实现Serializable接口。

4.单元素枚举类型。使用方法类似1,很简单。但是同时也实现了Serializable接口,并且也能自动防止反序列化生成新对象。如果不考虑线程,这是比前面三中都好的方式。

// Enum singleton - the preferred approach

public enum Elvis {

INSTANCE;

public void leaveTheBuilding() { ... }

}


5.延迟创建(按需创建或称懒汉模式)

Google公司的工程师Bob Lee写的新的懒汉单例模式

public class Singleton {

private static class SingletonHolder {

private static final Singleton INSTANCE = new Singleton();

}

private Singleton(){

}

public Singleton getInstance(){

return SingletonHolder.INSTANCE;

}

}

在加载singleton时并不加载它的内部类SingletonHolder,而在调用getInstance()时调用SingletonHolder时才加载SingletonHolder,从而调用singleton的构造函数,实例化singleton,从而达到lazy loading的效果。

6.Double-checked Locking模式在Java中是不能用的。原因有两个:

一是Java编译器处于优化的原因,生成的代码会不按照我们编写的顺序。极有可能先给instance变量赋值,然后再构造对象。这样一来在多线程环境下基于instance==null做判断就会得到错误的结果。

二是Java synchrorized保证了被保护的变量总是从内存中读取数据,而不是使用寄存器缓存的数据。但是当第一个线程已经创建好了对象,其他线程再来访问的时候,由于没有进入synchronized保护的代码,因此没有重新读取内存中的数据,因此有可能获取的是旧版本的数据。

详细理由参考下面的文章以及其参考的其他文章:

html">http://dev.firnow.com/course/3_program/java/javashl/2008414/110150.html