java singleton instantiation

社会主义新天地 提交于 2019-11-30 10:52:09

问题


I've found three ways of instantiating a Singleton, but I have doubts as to whether any of them is the best there is. I'm using them in a multi-threaded environment and prefer lazy instantiation.
Sample 1:

private static final ClassName INSTANCE = new ClassName();

public static ClassName getInstance() {
    return INSTANCE;
}

Sample 2:

private static class SingletonHolder { 
    public static final ClassName INSTANCE = new ClassName();
}

public static ClassName getInstance() {
    return SingletonHolder.INSTANCE;
}

Sample 3:

private static ClassName INSTANCE;

public static synchronized ClassName getInstance()
{
    if (INSTANCE == null)
        INSTANCE = new ClassName();

    return INSTANCE;
}

The project I'm using ATM uses Sample 2 everywhere, but I kind of like Sample 3 more. There is also the Enum version, but I just don't get it.

The question here is - in which cases I should/shouldn't use any of these variations? I'm not looking for lengthy explanations though (there's plenty of other topics about that, but they all eventually turn into arguing IMO), I'd like it to be understandable with few words.


回答1:


The most secure and easy way to implement a singleton in java is by using enums (like you mentioned):

public enum ClassName {
    INSTANCE;

    // fields, setters and getters
}

The enum semantics guarantees that there will be only one INSTANCE

If not using the enum approach, you must take care of quite a lot aspects, like race conditions and reflection. I've been breaking singletons of some frameworks, and abusing them, because they weren't properly written. The enum guarantees no one will break it.




回答2:


Sample 1 does not use lazy initialisation.

Sample 2 and 3 are both lazy. Sample 2 uses the Initialization on demand holder idiom (IODH) which has no synchronisation overhead. Therefore it is faster than Sample 3.

In Effective Java (Item 3), Joshua Bloch recommends that a single-element enum type is the best way to implement a singleton.

However, if you are unsure about the enum type, stick with IODH.




回答3:


First of all, make absolutely sure that you need a singleton, and that you want to provide "global-level" access to the singleton. I've found that in many cases clients of the singleton have no need to know that it is a singleton. Rather, they just need to get a service when they are instantiated.

Thus, regardless of how you obtain the singleton (if at all), consider changing the way your classes gain access to this object. While this means modifying constructors and changing "distribution changes", I've found that dependency injection frameworks reduce the cost. The DI framework can also then take care of singleton instantiation (e.g., Guice does that).

Aside from that. option 3 is the typical and most common (and thread safe) version that I'm familiar with. Option 1 is mostly for non-lazy initialization (not always acceptable). I've never seen 2 used.




回答4:


Sample 1: Use if you don't need a lazy Singleton.
Sample 2: Never use - it gets confusing with too much classes. And an inner class just to hold one variable seems to be a bit unnecessary. Sample 3: This is a lazy Singleton. Use it if you need it.



来源:https://stackoverflow.com/questions/4706216/java-singleton-instantiation

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