这是确保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; }
}