这是确保Java中只存在一个对象的单个实例的有效方法吗?

我在Mongodb中遇到了一些奇怪的错误,在Mongodb中,你应该使用Mongo单例。 我只是想确保这是有效的。

 public class DBManager { public static Mongo mongoSingleton = null; public static synchronized void getMongo(){ if(mongoSingleton == null){ mongoSingleton = new Mongo(); } return mongoSingleton; } } 

谢谢!

您必须将您的公共成员mongoSingleton设置为private并隐藏默认构造函数

所以

 private static Mongo mongoSingleton = null; private Mongo() { } 

Mongo类的实现

 public class Mongo { private static volatile Mongo instance; private Mongo() { ... } public static Mongo getInstance() { if (instance == null) { synchronized (Mongo.class) { if (instance == null) { // yes double check instance = new Mongo(); } } } return instance; } } 

用法

 Mongo.getInstance(); 

这是典型的Singleton模式,但Java中的首选方法是创建一个Enum:

 public enum DBManager { INSTANCE; // implementation here } 

然后,您可以通过以下方式引用实例:

 DBManager.INSTANCE 

请注意,在任何一种情况下(枚举或单例模式),结果是每个ClassLoader一个实例,而不是每个JVM。

  public static Mongo mongoSingleton = null; 

需要是

  private static Mongo mongoSingleton = null; 

除此之外,看起来不错。

如果您愿意放弃Lazy初始化,最简单的方法就是在对象创建时创建Singleton。

 public final class DBManager { private static final Mongo mongoSingleton = new Mongo(); private DBManager() {} public static Mongo getMongo() { return mongoSingleton; } } 

这样,您可以避免不必要的同步开销,否则会在每次调用此方法时出现这种开销。 只要Mongo本身是线程安全的,你的getMongo()方法也是线程安全的。

阅读Sun开发者关于Singletons的文章。

只需使用private static final Mongo mongo = new Mongo() ,甚至是public static final Mongo mongo = new Mongo() 。 它更简单,可能更快。

不,因为公共访问静态成员,您可以将其更改为您想要的任何实例。

更加理智的是以下内容

 public class DBManager { private static Mongo mongoSingleton = new Mongo(); public static Mongo getMongo(){ return mongoSingleton; } } 

单身的懒惰初始化被高估,通常不是必需的,并且导致更多的问题而不是好的。 使整个静态getter synchronized的天真方法很糟糕,因为每次都会执行同步(这是一个耗时的操作)。

有一些更好的方法,如双重检查锁定或按需初始化持有者 ,但最简单,通常最好的方法是Josh Bloch的枚举方法。 用单个元素制作一个enum ,你会得到一个防弹单身。

 public enum Mongo { INSTANCE; // instance fields, methods etc. as in any other class } 

这几乎在function上等同于具有private构造函数和public static final实例的类,但具有更简洁的语法和一些不错的底层function,这些function可以保证不会创建其他实例,甚至不能通过reflection反序列化

值得注意的是,这种方法并不一定非常渴望 。 单个INSTANCE是在Mongo类加载到JVM之后创建的,它在程序启动后没有发生 – 实际上它发生在第一次引用类时 – 在这种情况下意味着第一次static访问字段或方法。

如果除了INSTANCE和其他静态方法之外没有其他静态字段,那么这在第一次访问INSTANCE后真的会发生:

 Mongo mongo = Mongo.INSTANCE; 

换句话说,它实际上是懒惰的,没有显式同步的问题。

是的,但您不希望您的成员变量公开。 用户必须通过同步的getter来

如果您想逐步了解更多细节,可以点击此链接 – http://www.javabeginner.com/learn-java/java-singleton-design-pattern

以下是如何正确完成的一个示例。

 public class DBManager { private static Mongo mongoSingleton = null; public static synchronized void getMongo(){ if(mongoSingleton == null){ mongoSingleton = new Mongo(); } return mongoSingleton; } 

}