Java中的10个单例模式访问问题

Singleton设计模式是您将在Java应用程序中看到的最常见的模式之一,并且它也在核心Java库中大量使用。来自Singleton模式的问题在Java访谈中非常常见,并且对如何实现Singleton模式有着很好的了解。这也是我最喜欢的 设计模式面试问题之一, 并且有很多有趣的后续细节,这不仅仅是检查设计模式的知识,而且还检查编码,多线程方面这是非常重要的,而为实际应用工作。 在这篇文章中,列出了Java访谈中关于Singleton模式的一些最常见的问题。我没有提供这些问题的答案,因为他们很容易通过谷歌搜索,但如果你们需要我可以尝试修改本教程以包括答案。


正如之前所承诺的,并且收到了很多提供这些问题答案的请求,我决定更新这篇文章以及答案。顺便说一下,如果您正在准备采用Java技术进行面试,那么您可以在 Java面试问题 多线程面试问题 上查看我的收藏

Javarevisited中有大量资源可以帮助您进行面试准备。另一方面,如果你对设计模式教程更感兴趣,那么你可以在构建器设计模式上查看我的帖子



10关于Java中Singleton模式的采访问题

这里是我基于Singleton设计模式的面试问题集。它们是从各种Java访谈中收集的,并突出显示模式的关键方面以及它被打破的位置,如果您知道如何创建线程安全的单例以及实现此模式的不同方式以及每种方法的优缺点。问题始于:


什么是Singleton类?你之前用过Singleton吗?

Singleton是一个类,在整个应用程序中只有一个实例,并提供一个 getInstance() 方法来访问单例实例。在JDK中有许多类是使用Singleton模式实现的,如 java.lang.Runtime ,它提供了 getRuntime() 方法来访问它并用于获得 Java中的可用内存和总内存


哪些类是Singleton的候选者?Java中的Singleton是哪种类的?

在这里,他们检查候选人是否具有足够的单身人士使用经验。他是否熟悉Java中单例的优势/劣势或替代方案?

答:任何你希望整个应用程序可用的类,只有一个实例是可行的,可以成为Singleton的候选者。其中一个例子就是 Runtime 类,因为在整个Java应用程序中,只有一个运行时环境可以使 Runtime  Singleton成为正确的决定。另一个例子是GUI应用程序中的Popup等实用程序类,如果您想要显示带有消息的弹出窗口,则可以在整个GUI应用程序上有一个PopUp类,并随时获取其实例,然后用消息调用 show()


你可以在Java中编写Singleton类的getInstance()方法的代码吗?

大多数java程序员在这里都会失败,因为你可以根据他们编写的代码提出大量的后续问题。我见过很多程序员用双重检查锁定编写Singleton  getInstance() 方法,但他们并不十分熟悉在Java 5之前对单例的双重检查相关的警告。

答案:直到被问及时,不要使用双重检查锁定来编写代码,因为它更复杂,错误的可能性更大,但如果您对双重检查锁定有深入的了解,那么 挥发性变量 和延迟加载比这是您发光的机会。我分享了使用枚举编写单例类的代码示例,使用静态工厂,并在我最近的帖子中使用了双重检查锁定 为什么Enum Singleton在Java中更好 ,请看看那里。



使整个getInstance()方法同步还是仅仅关键部分足够好?哪一个你会更喜欢?

这真的是一个很好的问题,我主要要求快速检查候选人是否意识到性能会受到不必要的锁定影响。由于锁定只有在我们需要创建实例和其余时间时才有意义,因为它只是读取访问权限,所以锁定关键部分总是更好的选择。阅读有关同步的更多信息 如何使用Java进行同步
答案:这又与双重检查的锁定模式有关,良好的同步成本很高,并且当您将整个方法应用于 getInstance()方法时, 将会同步并满足它。由于同步只在单例实例的初始化期间需要,为了防止创建单例的另一个实例,最好只同步临界区而不是整个方法。单例模式也与 工厂设计模式 密切相关,其中 getInstance() 充当静态工厂方法。



什么是Singleton的懒惰和早期加载,你将如何实现它?

这是另一个很好的Singleton面试问题,它在理解与Java类加载相关的加载概念和成本方面的问题。我接受采访的其中许多人并不十分熟悉这一点,但它很了解这个概念。

回答:由于有很多方法可以实现Singleton,比如使用双重检查锁定或Singleton类以及在类加载期间初始化 静态  最终 实例。前者称为延迟加载,因为Singleton实例仅在客户端调用 getInstance() 方法时创建,而后者称为提前加载,因为Singleton实例在将类加载到内存中时创建。



给我一些来自Java Development Kit的Singleton模式的例子吗?

这是所有人都公开的问题,请在JDK中分享哪些类是Singleton。这个问题的答案是 java.lang.Runtime
答案:Java开发工具包中有许多类是使用单例模式编写的,下面是其中的几个:
  1. Java.lang.Runtime with getRuntime() method 
  2. Java.awt.Toolkit with getDefaultToolkit() 
  3. Java.awt.Desktop with getDesktop() 

Singleton中的双重检查锁定是什么?

关于Singleton模式的一个最被夸大的问题,并且真正需要完全理解才能正确使用它,因为Java 5之前的Java Memory模型警告说明了这个问题。如果一个人想出了使用 volatile关键字 与Singleton实例并解释它的解决方案,那么它真的表明它对Java内存模型有深入的了解,并且他不断更新他的Java知识。

答案:双重检查锁定是一种技术,用于在多线程环境中调用 getInstance() 方法时阻止创建另一个Singleton实例在下面的例子中显示的双重检查锁定模式中,单例实例在初始化之前检查两次。请参阅 此处 以了解有关Java中的双重检查锁定的更多信息。 

public static Singleton getInstance(){
      if_INSTANCE == null){
         synchronized(Singleton .class){
          //双重检查锁定 - 因为第二次检查Singleton实例的锁定
                if_INSTANCE == null){_
                     INSTANCE  =  new  Singleton();
                }
            }
         }
     return  _INSTANCE ;
}

只有当您需要延迟初始化时才应使用双重检查锁定,否则 使用Enum来实现单例 或简单静态最终变量。



你如何防止使用clone()方法创建另一个Singleton实例?

这种类型的问题通常会问一些问题,比如如何打破单例或Singleton在Java中不是Singleton。

答案:首选的方法不是实现Cloneable接口,为什么要创建Singleton的 clone() ,以及如果只是从 clone() 方法抛出Exception 作为“无法创建Singleton类的克隆”。



你如何防止使用反射创建另一个Singleton实例?

向所有人开放。在我看来,从构造函数中抛出异常是一个选项。
答案:这与之前的面试问题类似。由于Singleton类的构造函数应该是私有的,它可以防止从外部创建Singleton实例,但 Reflection可以访问私有的字段和方法 ,这会打开另一个实例的威胁。这可以通过从构造函数中抛出Exception作为“Singleton已经初始化”来避免



如何防止在序列化过程中创建另一个Singleton实例?

另一个需要知道 Java中 序列化知识的好问题,以及如何使用它来保存单例类。这对所有人都是开放的,但在我看来,使用readResolve()方法可以为你解决这个问题。
答案:您可以通过使用 readResolve() 方法来防止这种情况,因为在序列化过程中, readObject() 用于创建实例,并且每次都会返回新实例,但是通过使用readResolve,您可以将其替换为原始Singleton实例。我已经在我的帖子Enum中以共享代码的方式将它作为Java中的Singleton。这也是我之所以说使用Enum来创建Singleton的原因之一,因为枚举的序列化由JVM来处理,并提供了保证。


什么时候Singleton不是Java中的Singleton?

在Sun的Java站点中有一篇非常好的文章,它讨论了Singleton实际上不存在时的各种情况。Singleton和Singleton的多个实例是可能的。这篇文章的链接 http://java.sun.com/developer/technicalArticles/Programming/singletons/


除了这些关于Singleton模式的问题之外,我的一些读者还贡献了更多的问题,这些问题都包含在这里。感谢你们的贡献。


为什么你应该避免使用单态反模式并用DI代替?

答案:单例依赖注入:每个需要访问单例的类都通过构造函数或DI容器获取对象。


为什么辛格尔顿是反模式 

随着越来越多的类调用 getInstance() ,代码变得越来越紧密,单一,不可测试,难以改变,难以重用,因为不可配置,隐藏的依赖关系。此外,如果您不经常调用 getInstance (即一次),则不需要这种笨拙的双重检查锁定


有多少种方法可以在Java中编写Singleton类?

答案:我知道至少有四种方法可以在Java中实现Singleton模式
  1. 通过同步getInstance()方法来实现单例
  2. 带有在类加载期间初始化的公共静态final字段的单例。
  3. 由静态嵌套类生成的单例,也称为Singleton持有者模式。
  4. 从使用枚举的Java 5上进行


如何在Java中编写线程安全的Singleton?

答案:线程安全Singleton通常指的是写入 线程安全代码 ,如果同时由多个线程调用,则会创建一个且仅有一个Singleton实例。有很多方法可以通过使用上面显示的双重检查锁定技术以及使用通过类加载器初始化的 Enum 或Singleton 来实现此目的

最后几个问题是你的实践,由Mansi贡献,谢谢Mansi 

14)Singleton vs Static Class?
15)什么时候选择Singleton over Static Class?
16)你可以用Java中的Static Class替换Singleton吗?
17)java中单例和静态类的区别?
18)Singleton优于静态类的优点?


我在我的文章中讨论了几个这些问题的答案,即 Singleton和Java中的静态类 - 优点和缺点
https://javarevisited.blogspot.com/2011/03/10-interview-questions-on-singleton.html

你可能感兴趣的:(java基础,多线程)