Java 2关于单例模式/即时初始化和同步

Java 2关于单例模式/即时初始化和同步,java,synchronization,singleton,lazy-loading,eager-loading,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 (Singl

(摘自维基百科)

//延迟初始化:

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;
   }
}
//即时初始化:

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()而不是代码块(消除双重检查)将如何影响我的程序


谢谢。

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

  • 您并不总是使用每个类,可能程序中的某些路径使用实例,而某些路径不使用实例
  • 同步方法而不是块将意味着每次有人想要引用时都必须获取锁。这是非常浪费的。您应该始终保持
    同步
    块尽可能小,以最小化锁争用

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

    在运行时需要该类之前,静态字段/方法不会被实例化/调用,因此ReportABug类可能有1000个静态字段,但祈祷好运,它们永远不会消耗任何内存,因为该类从未加载

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

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

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