【问题标题】:java multithreaded lazily initialized singleton which approach?java多线程懒惰初始化单例的方法有哪些?
【发布时间】:2018-07-15 21:10:27
【问题描述】:

以下两种在java中延迟初始化线程安全单例的方法是否正确?有性能差异吗?如果不是,那我们为什么要使用 Holder 模式(Singleton2)而不是像 Singleton1 那样保持简单?

提前致谢。

class Singleton1 {
    private Singleton1() {
        System.out.println("Singleton1-Constructor");
    }

    private static final Singleton1 inst1 = new Singleton1();

    public static Singleton1 getInst1() {
        return inst1;
    }
}

class Singleton2 {
    private Singleton2() {
        System.out.println("Singleton2-Constructor");
    }

    public static class Holder {
        private static final Singleton2 holderInst = new Singleton2();
    }

    public static Singleton2 getInst2() {
        return Holder.holderInst;
    }
}

public class App {
    public static void main(String[] args) {
        Singleton1.getInst1(); // without this statement the Singleton1 constructor doesnt get called.
        Singleton2.getInst2(); // without this statement the Singleton2 constructor doesnt get called.
    }
}

【问题讨论】:

  • 您的第二个选项Singleton2 允许您在不触发实例构造的情况下执行其他静态方法(如果有的话)。但是,通常Holder 类是private static,并且您在单例类上使用public static 方法公开实例。至少我一直都是这么看的。
  • 对于那些认为它重复的人......请看下面 Pietro Boido 提供的解释。建议的帖子中没有人以同样的方式解释它。有些人需要更多的解释,所以请不要因为你认为已经有类似的问题被问过而扼杀问题。谢谢,
  • This answer to the possible duplicate 回顾了 Pietro Boido 在他的回答中所说的内容。不过,我会说我认为 Pietro 更直接。

标签: java multithreading thread-safety singleton lazy-initialization


【解决方案1】:

Singleton1 并不是真正的惰性,因为如果您向 Singleton1 添加任何其他方法并从主类调用它,那么静态 inst1 将被初始化。

试试这个:

public class Singleton1 {
  private Singleton1() {
    System.out.println("Singleton1-Constructor");
  }

  private static final Singleton1 inst1 = new Singleton1();

  public static Singleton1 getInst1() {
    return inst1;
  }

  public static void foo() {
  }
}

public class Singleton2 {
  private Singleton2() {
    System.out.println("Singleton2-Constructor");
  }



  public static class Holder {
    private static final Singleton2 holderInst = new Singleton2();
  }

  public static Singleton2 getInst2() {
    return Singleton2.Holder.holderInst;
  }

  public static void bar() {
  }
}

public class LazyInitializationApp {

  public static void main(String[] args) {
    Singleton1.foo();
    Singleton2.bar();
  }
}

现在运行应用程序将打印:

Singleton1-Constructor

但它不会打印 Singleton2-Constructor,因为它真的很懒。

【讨论】:

  • 感谢 Pietro Boido 的详细回复。但是从线程安全的角度来看,这两种解决方案都安全吗?
猜你喜欢
  • 1970-01-01
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 2022-12-25
  • 1970-01-01
相关资源
最近更新 更多