单身模式

时间:2010-12-05 05:35:43

标签: java design-patterns singleton

以下代码段是直截了当的,

public MyClass getInstance() {
    if(uniqueInstance == null) {
        uniqueInstance = new MyClass();
    }
    return uniqueInstance;
}

以下人员做了什么?

public MyClass getInstance() {
    if(uniqueInstance == null) {
        synchronized(MyClass.class) {
            uniqueInstance = new MyClass();
        }
    }
    return uniqueInstance;
}

4 个答案:

答案 0 :(得分:5)

尝试使线程安全,以防止由至少两个同时进入if块的线程引起的竞争条件是一个不好的尝试。

更安全的方法是添加额外的空检查,也称为double-checked locking

public MyClass getInstance() {
    if (uniqueInstance == null) {
        synchronized(MyClass.class) {
            if (uniqueInstance == null) {
                uniqueInstance = new MyClass();
            }
        }
    }
    return uniqueInstance;
}

但是,我通常更喜欢Just Create One pattern而非单身人士。

答案 1 :(得分:3)

这对于线程安全来说有点保险。

来自javaworld文章here

  

同步方法保证   调用方法不能   中断。

主要思想是,如果你没有synchronized块,那么2个线程可以调用getInstance并重新初始化对象,从而可能丢失任何状态数据(如果你甚至应该在单例中有状态数据)

答案 2 :(得分:3)

恕我直言你应该先从最简单的选项开始。最简单的单例是一个带有一个条目的枚举。鉴于类是懒惰加载,这仍然会给你延迟加载,除非直接引用类,这不容易发生。

enum Singleton {
   INSTANCE;
}

为避免意外加载,您可以使用内部类。

class Singleton {
    static class SingeltonHolder {
        static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

请注意;两种解决方案都不需要同步,因为它们使用了类加载是线程安全的事实。

总之;在某些情况下需要锁定,但不要使其比需要的更复杂。

答案 3 :(得分:1)

第二个做同样的事情,除了:如果你使用第一个,如果创建一个新的MyClass需要一些时间会发生什么,在那段时间,其他人也会调用MyClass.getInstance()?您可能最终得到两个实例。第二个版本锁定实例化行,因此如果另一个类试图同时调用,它将等到第一个完成。