2

(来自维基百科)

//延迟初始化:

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

4 回答 4

4

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

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

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

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

于 2012-08-12T12:00:45.937 回答
2
  1. 您并不总是使用每个类,也许通过您的程序的某些路径使用实例,而有些则不使用。
  2. 同步方法而不是块意味着每次有人想要引用时都必须获取锁。这是非常浪费的。您应该始终使您的synchronized块尽可能小,以尽量减少锁争用。
于 2012-08-12T11:50:17.630 回答
0

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

于 2012-08-12T11:47:06.207 回答
0
  1. 这种技术称为双重检查锁定,在 JDK 1.5+ 中应避免使用。它用于低于 1.5 的 Java 版本,因为获取内部锁(进入同步块)的成本很高。这不再是真的,应该避免双重检查锁定。

参考实践中的并发 16.7 双重检查锁定反模式。不要这样做。

于 2016-11-08T10:53:59.697 回答