3

我在使用 Mongodb 时遇到了一些奇怪的错误,而在 Mongodb 中,您应该维护Mongo单例。我只是想确保这实际上是有效的。

public class DBManager {
    public static Mongo mongoSingleton = null;

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

谢谢!

4

9 回答 9

6

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

所以

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();
于 2012-05-23T23:31:20.437 回答
5

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

public enum DBManager {
    INSTANCE;

    // implementation here
}

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

DBManager.INSTANCE

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

于 2012-05-23T23:36:58.110 回答
1

随便用private static final Mongo mongo = new Mongo(),甚至public static final Mongo mongo = new Mongo()。它更简单并且可能更快。

于 2012-05-23T23:32:53.167 回答
1

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

更理智的是以下

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

    public static Mongo getMongo(){
       return mongoSingleton;
    }
}
于 2012-05-23T23:27:44.820 回答
1
 public static Mongo mongoSingleton = null;

需要是

 private static Mongo mongoSingleton = null;

除此之外,看起来不错。

于 2012-05-23T23:28:23.870 回答
1

如果您愿意放弃延迟初始化,那么最便宜的方法是在对象创建时简单地创建单例。

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

    private DBManager() {}

    public static Mongo getMongo() {
         return mongoSingleton;
    }
}

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

在此处阅读有关单例的 Sun 开发人员文章。

于 2012-05-23T23:31:59.767 回答
1

单例的延迟初始化被高估了,通常没有必要,并且导致的问题多于好处。制作整个静态 getter 的天真方法是不好的,因为每次都会synchronized执行同步(这是一个耗时的操作)。

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

public enum Mongo {

    INSTANCE;

    // instance fields, methods etc. as in any other class
}

这在功能上几乎等同于具有private构造函数和public static final实例的类,但具有更简洁的语法和一些不错的底层特性,这些特性不可动摇地保证不能创建其他实例,即使通过反射反序列化也不行。

值得注意的是,这种方法不一定是急切的。单曲INSTANCE是在Mongo类加载到 JVM 之后创建的,它不会在程序启动后立即发生 - 实际上它发生在第一次引用类时- 在这种情况下,这意味着第一次static字段或方法被访问。

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

Mongo mongo = Mongo.INSTANCE;

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

于 2012-05-23T23:52:39.897 回答
0

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

于 2012-05-23T23:29:00.963 回答
0

如果您想了解更多详细信息,请一步一步 - 您可以点击此链接 - 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;
}

}

于 2012-05-23T23:32:01.103 回答