Singleton模式可能是应用最广泛的模式之一了, 但有些错误的应用。
Singleton的实现: 有两种方式, 如下:
1. class Test {
public static final Test instance = new Test();
private Test() {}
}
2. class Test {
private static final Test instance = new Test();
private Test() {}
public static Test getInstance() {
return instance;
}
}
这两种方法都要求构造器是私有的, 这样就可以防止该类外的对象创建新的TEST对象。
但相对而言, 推荐使用第二种方法, 因为其更具有灵活性,当我们改变创建对象的方式的时候, 不需要改动客户代码。 第一种方法较第二种有一点完全可以忽略不计的效率的提高。
但应避免如下代码实现Singleton:
class Test {
private static Test singleton = null;
private Test() {}
public Test getSingleton() {
if(singleton == null) {
singleton = new Test();
}
return singleton;
}
}
因为严格上讲, 这并不能完全实现Singleton模式,而且会导致程序出错, 这同著名的线程问题--DCL实效的原理是完全一样的:
JVM创建对象的过程可以分为几个步骤:创建空间, 把所有的变量赋值位默认值, 初始化。。。 当有两个线程A和B同事进入该方法, A先执行, A创建Test实例的空间, 这时,因为CPU的指令流机制,时间片段正好轮到B线程, 这时B判断singleton是否为NULL, 因为A已经为Test的实例分配了空间, 所以JVM认为实例已经创建了, B继续执行, 更糟糕的是B调用了singleton, 这时因为他并没有初始化完全, 所以抛出NullPointerException, 太糟糕了!