如何在java中创建一个真正的单例?

时间:2009-09-29 21:06:52

标签: java singleton absolute

在多个类加载器中使用时,我遇到了我的单例问题。 E.g由多个EJB访问的Singleton。有没有办法创建一个在所有类加载器中只有一个实例的单例?

我正在寻找使用自定义类加载器或其他方式的纯java解决方案。

4 个答案:

答案 0 :(得分:5)

唯一的方法是让单个类加载单个类 - 例如,将该jar文件放在bootclasspath中。

静态变量本质上与加载包含该变量的类的类加载器相关联。这就是它的工作方式。如果您只需要一个实例,则需要该类仅由一个类加载器加载。

答案 1 :(得分:5)

JavaEE应用服务器通常通过将单例设置为“服务”来解决此问题,其确切的定义和配置取决于所讨论的应用程序服务器。

例如,在JBoss中,您可以使用xyz-service.xml描述符来设置挂起JNDI或JMX树的单例对象,并且您的应用程序组件(例如您的EJB)将从树中获取单例。这在某种程度上保护了你的基础类加载器语义。

答案 2 :(得分:3)

J2EE的设计考虑了集群,因此它支持的任何设计都必须使用多个JVM。我从你的问题中得知你不关心集群环境,所以在你的应用服务器上简单地插入JNDI应该这样做。在Glassfish中,称为lifecycle listener。在启动之后,将您的单例插入JNDI,然后让其他所有内容进行JNDI查找以找到它。

请注意,GlassFish仍然可能会让您陷入困境,因为它可以将类序列化为JNDI,从而导致您获得不同的实例。我怀疑它在一个JVM中实际上是这样做的,但是在你尝试之前你不会知道。

真正的底线答案是J2EE对全球真正的单身人士怀有敌意,围绕这个问题的J2EE方法是重新思考解决方案。类似于数据库来保存值或其他一些外部服务可以确保只存在一个数据实例(即使表示数据的多个对象实例)是J2EE方式。

答案 3 :(得分:0)

要达到TRUE Singleton,您必须遵循以下指南:

  1. 将您的课程设为final。其他人不能对它进行分类并再创建一个实例
  2. 将您的Singleton实例设为private static final
  3. 提供private constructorpublic getInstance()方法。
  4. 确保Singleton
  5. 加载了此one ClassLoader only课程
  6. 覆盖readResolve()方法并返回相同的实例,而无需在反序列化过程中创建新实例。
  7. 示例代码:

    final class  LazySingleton {
        private LazySingleton() {}
        public static LazySingleton getInstance() {
            return LazyHolder.INSTANCE;
        }
        private static class LazyHolder {
            private static final LazySingleton INSTANCE = new LazySingleton();
        }
        private Object readResolve()  {
            return LazyHolder.INSTANCE;
        }
    }
    

    有关详细信息,请参阅下面的SE问题:

    What is an efficient way to implement a singleton pattern in Java?