Is this a valid way to ensure only a single instance of an object exists in Java?

*爱你&永不变心* 提交于 2020-01-02 08:39:23

问题


I have been getting some strange errors with Mongodb, and in Mongodb, you are supposed to mainatin the Mongo singleton. I just wanted to make sure that this is infact valid.

public class DBManager {
    public static Mongo mongoSingleton = null;

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

Thanks!


回答1:


You have to set your public member mongoSingleton as private and to hide the default constructor

so

private static Mongo mongoSingleton = null;

private Mongo() {

}

the class Mongo implementation

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;
    }
}

usage

Mongo.getInstance();



回答2:


This is the typical Singleton pattern, but the preferred method in Java is to create an Enum:

public enum DBManager {
    INSTANCE;

    // implementation here
}

You can then refer to the instance via:

DBManager.INSTANCE

Note that in either case (enum or singleton pattern), the result is one instance per ClassLoader, NOT per JVM.




回答3:


 public static Mongo mongoSingleton = null;

needs to be

 private static Mongo mongoSingleton = null;

Other than that, looks good.




回答4:


The cheapest way to do this, if you are willing to forego Lazy initialization, is to simply create the Singleton on object creation.

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

    private DBManager() {}

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

This way, you can avoid the unnecessary synchronization overhead which would otherwise be present on every call to this method. As long as Mongo itself is thread safe, your getMongo() method is thread-safe as well.

Read the Sun developer article on Singletons here.




回答5:


Just use private static final Mongo mongo = new Mongo(), or even public static final Mongo mongo = new Mongo(). It's simpler and potentially faster.




回答6:


no, because public access to the static member you can change it to whatever instance you want.

More sane would be the following

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

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



回答7:


Lazy initialization of singletons is overrated, usually not necessary and causes more problems than good. The naive approach to make the whole static getter synchronized is bad, because the synchronization (which is a time consuming operation) is performed every time.

There are some better approaches such as double-checked locking or the initialization-on-demand holder, but the simplest and usually the best approach is Josh Bloch's enum approach. Make an enum with a single element and you get a bullet proof singleton.

public enum Mongo {

    INSTANCE;

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

This is almost functionally equivalent to a class with a private constructor and a public static final instance, but with more concise syntax and some nice under-the-hood features that unshakeably guarantee that no other instance can be created, not even through reflection or deserialization.

It is worth noting that this approach isn't necessarily eager. The single INSTANCE is created just after the Mongo class is loaded into the JVM, which doesn't happed right after the program starts - actually it happens on the first time the class is referenced - which in this case means on the first time a static field or a method is accessed.

And if there are no other static fields other that INSTANCE and no static methods, then this really happens after the first time the INSTANCE is accessed:

Mongo mongo = Mongo.INSTANCE;

In other words, it actually is lazy without the problems of explicit synchronization.




回答8:


Yes but you don't want your member variable to be public. Users have to come via your synchronised getter




回答9:


If you want to see in more details, step by step- you can follow this link- http://www.javabeginner.com/learn-java/java-singleton-design-pattern

Below is one example how to do it properly.

public class DBManager {
private static Mongo mongoSingleton = null;

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

}



来源:https://stackoverflow.com/questions/10729249/is-this-a-valid-way-to-ensure-only-a-single-instance-of-an-object-exists-in-java

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!