当前位置: 首页 > 面试题库 >

Java Singleton实例化

谭浩皛
2023-03-14
问题内容

我已经找到了实例化Singleton的三种方法,但是我怀疑其中是否有最好的方法。我在多线程环境中使用它们,并且更喜欢延迟实例化。
范例1:

private static final ClassName INSTANCE = new ClassName();

public static ClassName getInstance() {
    return INSTANCE;
}

范例2:

private static class SingletonHolder { 
    public static final ClassName INSTANCE = new ClassName();
}

public static ClassName getInstance() {
    return SingletonHolder.INSTANCE;
}

范例3:

private static ClassName INSTANCE;

public static synchronized ClassName getInstance()
{
    if (INSTANCE == null)
        INSTANCE = new ClassName();

    return INSTANCE;
}

我正在使用ATM的项目到处都使用Sample 2,但我还是更喜欢Sample 3。还有Enum版本,但是我不明白。

这里的问题是-
在什么情况下我应该/不应该使用这些变体中的任何一个?我并不是在寻找冗长的解释(对此还有很多其他话题,但是最终它们都变成了IMO的争论),我希望它能用几句话就能理解。


问题答案:

在Java中实现单例的最安全,最简单的方法是使用枚举(如您提到的那样):

public enum ClassName {
    INSTANCE;

    // fields, setters and getters
}

枚举语义保证只有一个 INSTANCE

如果不使用枚举方法,则必须注意很多方面,例如竞争条件和反思。我一直在打破某些框架的单例,并且滥用它们,因为它们的编写方式不正确。枚举保证没有人会破坏它。



 类似资料:
  • 假设你有一个绘制了很多模型的场景,而大部分的模型包含的是同一组顶点数据,只不过进行的是不同的世界空间变换。想象一个充满草的场景:每根草都是一个包含几个三角形的小模型。你可能会需要绘制很多根草,最终在每帧中你可能会需要渲染上千或者上万根草。因为每一根草仅仅是由几个三角形构成,渲染几乎是瞬间完成的,但上千个渲染函数调用却会极大地影响性能。 如果我们需要渲染大量物体时,代码看起来会像这样: for(un

  • 负载均衡实例是一个运行的负载均衡服务,通过设置的虚拟IP接收流量并将其转发分配给后端服务器。 负载均衡服务即为了保证业务的高可用,将多台业务虚拟机或服务器等虚拟成一个逻辑的应用服务池,通过虚拟IP向外提供服务,用户访问虚拟IP时,负载均衡服务将监听指定端口将来自用户的请求分发给后端的虚拟机或服务器处理。 一个完整的负载均衡主要包括3部分,负载均衡实例、监听和后端服务器组。用户在配置负载监听服务时需

  • 实例在面向对象程序设计中是指类经过实例化后的对象。本章节中所讲述的实例指的是 LCUI 应用实例,你可以将其理解为用 C++ 代码定义的 LCUIApplication 类型的对象,不过由于 LCUI 是 C 语言写的,应用实例的相关方法只不过是一些名字以 LCUI_ 开头的函数,没法像 C++ 那样用 class 关键字显式的将相关数据和方法抽象为一个类,因此实例的存在感比较弱。 LCUI 应用

  • 问题内容: 当用Java实例化一个对象时,真正进入内存的是什么? 是否包含父级构造函数的副本? 投射时,为什么隐藏数据成员的行为与重写方法不同? 我理解为使您正确使用这些东西而通常给出的抽象解释,但是JVM如何真正做到这一点。 问题答案: 实例化对象时,实际上仅“静态”数据以及创建该对象的对象类型的引用被“创建”。 没有方法被复制过。 创建它的类的“引用”实际上是一个指针调度表。该类可用的每个方法

  • 问题内容: 扩展初始化接口时提出的问题?),我们在实例化接口的同时用实现的类对其进行初始化。 我的问题是,为什么首先要使用Interface实例化它?为什么我不能直接用实现的类实例化它?例如。: Doc是接口,而SimpleDoc正在实现它。SimpleDoc有什么问题?mydoc = new SimpleDoc(); 哪里会失败? 问题答案: 通常,最好的方法是依赖系统中的抽象类型(接口或抽象类

  • 为方便框架的后续升级,thinkcmf与thinkphp框架模型操作方法完全一致。 所以这里是支持thinkphp原生的M方法和D方法来实例化模型; 实例化模型的好处: 可以实现自动完成,自动校验功能。使用模型封装的方法。分离M层和C层; M方法: M(['模型名'],['数据表前缀'],['数据库连接信息']); //实例化模型 $User=M('User'); // 执行具体的数据操作 $Us