Java 单亲模式访谈
我最近在接受以下代码采访时被问及与java相关的问题,因为我对java非常陌生,几乎不使用java编写代码,所以我真的不知道下面的代码做什么 问题是 选择用以下代码描述最糟糕情况的选项:Java 单亲模式访谈,java,singleton,Java,Singleton,我最近在接受以下代码采访时被问及与java相关的问题,因为我对java非常陌生,几乎不使用java编写代码,所以我真的不知道下面的代码做什么 问题是 选择用以下代码描述最糟糕情况的选项: public class Bolton { private static Bolton INST = null; public static Bolton getInstance() { if ( INST == null ) {
public class Bolton {
private static Bolton INST = null;
public static Bolton getInstance()
{
if ( INST == null )
{
INST = new Bolton();
}
return INST;
}
private Bolton() {
}
}
下面是这个问题的选项
以上哪个选项是正确的?为什么呢?面试官基本上是想检查你对单身模式的了解程度。这种模式会被打破吗?。是的。检查或谷歌-当singleton不是singleton时 最好的方法是按照Joshua Bloch的建议使用这是一个 单例模式的思想是一个类只有一个可用实例。因此,
constructor
被设置为private
,在这种情况下,该类维护一个getInstance()
方法,该方法调用该类中的现有实例变量INST
,或者为正在执行的程序创建一个新的实例变量。答案可能是1,因为它不是线程安全的。它可能会被我之前写下的3弄糊涂,但从技术上讲,这是设计的,所以实际上不是一个缺陷
下面是一个来自维基百科的线程安全单例模式延迟初始化的示例:
public class SingletonDemo {
private static volatile SingletonDemo instance = null;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class){
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}
}
将实例变量设置为告诉Java从内存中读取它,而不是在缓存中设置它
帮帮忙
阅读更多关于“惰性初始化”单例会发生什么的信息应该同步getInstance()
方法,否则如果多个线程同时调用getInstance()
,可能会创建多个实例。所以我会选择选项1
可以创建多个Bolton实例
由于上述代码中缺少同步,因此此选项是正确的
假设两个线程同时检查null
,两个线程都会发现值是null
,并且都会调用构造函数(它会拒绝singleton)
此外还有其他问题,即使两个线程不一起检查null
,但假设一个线程调用构造函数;但是构造函数在构建对象之前不会返回(假设对象的创建成本很高并且需要时间),因此在构造函数返回其他线程之前,可能会检查null
条件,并且仍然会发现对象为null
,因为对象尚未构建
在这种情况下,一些先决条件被称为检查然后行动,这是种族的罪魁祸首
对于singleton,有两种标准正在使用:
这是另一篇伟大的文章,它讨论了原始答案是只创建了一个博尔顿实例 通过反射,我们可以创建许多对象,即使构造函数是私有的
在多线程环境中,有机会创建多个实例
通过序列化可以创建多个对象 简单的答案是
2)永远不会创建Bolton
,因为当您创建实例时,构造函数将在构造函数初始化内部调用调用getInstance方法,然后答案将是创建单个实例 当我们只想拥有这个类的一个对象时,我们使用单例模式,它将在任何地方使用。因此,为了限制该类创建许多对象,我们应该对该类的构造函数使用private
。并创建一个public
函数来返回此类的对象
public class MethodWin {
private int isLoggedOn=0;
private static MethodWin objectMethodWin = new MethodWin();
private MethodWin() { }
public static MethodWin getInstance() {
return objectMethodWin;
}
public void setIsLoggedOn(int value) {
this.isLoggedOn=value;
}
public int getIsLoggedOn() {
return this.isLoggedOn;
}
}
因此,当我们需要创建此对象时,我们应该:
MethodWin meth = MethodWin.getInstance();
我会和1一起去。基本上,没有线程同步。这将允许两个或多个线程创建该类的多个实例。我还建议它打破Java命名惯例,但这不是一个选项。从技术上讲,2也是正确的。仅从这段代码中,将永远不会创建
Bolton
(实际上不会调用getInstance()。:)@杰克·斯托弗勒:我喜欢你的思维方式,我将把这一点添加到我们的面试问题中;)好吧,我站在更正,同步问题实际上没有发生在我身上。。。是时候重写我的单身汉了@Thihara欢迎来到我的世界:谢谢你的详细回答。有人问我时,我选择了3。正如我所提到的,这是一个疯狂的猜测,我对Java知之甚少(.但这对我将来会有帮助,否则我可能会开始用Java弄脏我的手。:)选择2怎么样?基于@JakeStoeffler注释。将创建一个Bolton
,但仅作为实例变量。我认为他指的是没有创建调用它的main()
方法的事实。-1对于@Christopher来说,你的代码中似乎有一个输入错误-你错误地将getInstance
方法包含在构造函数体中实际上Bloch说双重检查是一种选择的技术,但是变量必须声明为volatile
(因为如果实例已经初始化,则没有锁)。当然,一旦您修复了该变量,我将恢复为+1:),您的答案非常全面。@Javier我已经编辑过了。我的错。我还读到,即使我们进行双重锁定,也不安全。对于该枚举,应使用模式。