2关于Singleton模式/ Eager初始化和同步

时间:2012-08-12 11:41:26

标签: java synchronization singleton lazy-loading eager-loading

(来自维基百科)

//延迟初始化:

public class Singleton {

    private static volatile Singleton instance = null;

    private Singleton() {   }

    public static Singleton getInstance() {
            if (instance == null) {
                    synchronized (Singleton.class){
                            if (instance == null) {
                                    instance = new Singleton();
                            }
                  }
            }
            return instance;
    }
}

//急切的初始化:

public class Singleton {
   private static final Singleton instance = new Singleton();

   private Singleton() {}

   public static Singleton getInstance() {
      return instance;
   }
}

“如果程序使用该类,但可能不是单例实例本身,那么您可能希望切换到延迟初始化。”

1 - 不确定我是否得到了它。为什么程序不能使用类?为什么我不能通过添加属性/方法来解决它?恒定参考应如何改变?

2 - 在延迟初始化中 - 假设多线程发生,同步getInstance()而不是代码块(摆脱双重检查)会如何影响我的程序?

谢谢。

4 个答案:

答案 0 :(得分:4)

1 - 您的应用程序可能包含各种罐子,但您不一定会使用每个罐子中的所有功能。此外,应用程序的用户可能无法使用您内置的所有功能。例如,如果您有一个ReportABug类,它们可能永远不会从菜单中激活该功能,因为您是一个非常棒的程序员; - )

在运行时需要类之前,不会实例化/调用静态字段/方法,因此ReportABug类可能有1000个静态字段,但是手指交叉,它们永远不会消耗任何内存,因为从不加载类。

他们的观点是,具有单例(或多个)的类可能具有不访问单例的其他静态方法。

2 - 您可以将方法与Singleton类对象同步,但是每次调用getInstance都会产生开销,只需检查instance == null(它是一个机器周期)就便宜得多。有可能另一个线程可以抢占你的线程并在外部== null检查后创建实例,因此两个测试都是必需的。

答案 1 :(得分:2)

  1. 您并不总是使用每个类,也许您的程序中的某些路径使用该实例,而某些路径则不使用。
  2. 同步方法而不是块意味着每次有人想要引用时都必须获取锁。这非常浪费。您应该始终尽可能减少synchronized块,以尽量减少锁争用。

答案 2 :(得分:0)

1- java中有很多类,并不总是全部使用它们。如果我用急切初始化定义了一个singelton类,并且你不需要这个类,我最终会浪费内存。

答案 3 :(得分:0)

  1. 这种技术称为双重检查锁定,在JDK 1.5+中应该避免使用。它用于低于1.5的Java版本,因为获取内部锁(进入同步块)非常昂贵。它不再是真的,应该避免双重检查锁定。
  2. 实践中的参考并发16.7双重检查锁定反模式。不要这样做。