如果使用INSTANCE holder类来实现Singleton Pattern,编译器将生成另一个名为classname $ 1.class的类文件。您可以通过以下链接找到问题:here 。所以我的问题是Singleton Pattern的解决方案是什么?仔细检查?
答案 0 :(得分:3)
您可以使用简单的枚举。
public enum Singleton {
INSTANCE;
}
您可以简单地INSTANCE
访问Singleton.INSTANCE
,而不是调用getInstance()
方法。默认情况下,创建Enum实例是线程安全的。
答案 1 :(得分:3)
您似乎在问这个单例代码如何实现线程安全初始化:
public final class Test {
static final class TestHolder {
private static final Test INSTANCE = new Test();
}
private Test() {}
public static Test getInstance() {
return TestHolder.INSTANCE;
}
}
解决方案的线程安全性得到保证,因为:
final
变量而无需进一步同步。没有进行双重检查锁定。
请注意,此特定模式是线程安全且延迟初始化。如果你想要非线性初始化的线程安全单例,那么:
public final class Test {
private static final Test INSTANCE = new Test();
private Test() {}
public static Test getInstance() {
return INSTANCE;
}
}
“enum
作为单身人士”的做法也是可以接受的......尽管工程师Dollery说道。
使用双重检查锁定的延迟初始化可以从Java 5开始正确实现(如果使用volatile
正确执行),但在Java 1.4.x及更早版本中,习惯用法已被破坏。
答案 2 :(得分:1)
我会在jdk 1.5之后使用enum。查看htis链接了解详情:http://javarevisited.blogspot.in/2012/07/why-enum-singleton-are-better-in-java.html
下面的文章解释了为什么双重检查锁定可能是错误的选择 [正如Thomas指出的那样,beow文章中提到的双重检查锁定问题已在Java 1.5中修复]:http://www.ibm.com/developerworks/java/library/j-dcl/index.html < / p>
答案 3 :(得分:1)
根据您的部署体系结构,在Java中实现单例变得非常困难。当你谈论单身人士时,你还必须谈论他们的范围/背景。因为很少有人理解这些单身人士经常被称为邪恶,被认为是反模式。
如果您在应用程序服务器之外部署到单个jvm,那么惯用方法是在其自身内实现该类的私有最终静态实例,并通过适当命名的方法公开它(getInstance()是常见的) ,并使类的构造函数私有。这是一个约束单个类加载器和单个jvm的单例。
然而,这种情况非常罕见。
在所有其他情况下,您必须考虑类加载器问题以及将代码部署到多个jvms /服务器的问题。在典型的Java EE应用程序容器中,通常使用自己的类加载器加载每个war。如果每个战争都依赖于一个包含单身的战利品,他们每个人都会得到他们自己的单身人士副本。这可能没问题,如果单例是用于数据库连接,那么你可以使用它们。但是,如果单例应该保护对有限资源的访问,那么这不会很好,因为你将有一个类能够按webapp访问该资源。你的单身人士的范围是容器范围。
在完整的企业部署中,集群和实时故障转移会变得更糟。在此环境中,您可以同时运行许多软件副本。很难想象在这个范围内工作的只有java的单例 - 企业范围。在这个级别,你需要弄清楚单一创建或执行的单一事实来源(如果可以有多个实例,但一次只能处理一个请求),以及你创建的所有单例同一类型必须遵循单一的事实来源 - 企业信号量。