10

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.

jurchiks
  • 1,354
  • 4
  • 25
  • 55

4 Answers4

20

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.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • But how do I use it? For example, I have this: public class MyClass { public enum ClassName { INSTANCE; //do I put all my methods here instead of... } // here as I normally would? } Edit: damn it, no formatting on comments?? HATE it! – jurchiks Jan 16 '11 at 15:49
  • 1
    you write your singleton fields and methods below. And then access them via `ClassName.INSTANCE.doSomething(foo)` – Bozho Jan 16 '11 at 15:50
  • @jurchiks: yes. Elsewhere, you'd call `ClassName.INSTANCE.methodName()` to use the singleton methods (or perhaps use static imports to get rid of the `ClassName.INSTANCE.`) part. – Carl Jan 16 '11 at 15:51
  • one other note: if I understand it correctly, the `enum` approach is definitely non-lazy. – Carl Jan 16 '11 at 15:54
  • @Carl, class loading is lazy. You only have a problem if you load the class but you don't want the INSTANCE loaded. You can't load them independently. – Peter Lawrey Jan 16 '11 at 16:56
  • Another small question, somewhat offtopic: if I understand correctly, the INSTANCE is a single object that gets passed around to every class that calls it and it is never in 2 places simultaneously. T/F? – jurchiks Jan 16 '11 at 17:32
  • Instance is a single object. It can be used in multiple places simultaneously. – Bozho Jan 16 '11 at 19:29
  • Then how could I guarantee that fields in that instance don't get messed up by, for example, writing from 2 places at the same time? Or is it that by getting an instance, you make a copy of the object each time? And anything you do to the copy doesn't reach the original? – jurchiks Jan 16 '11 at 22:12
  • no copies. Just one object. If you want the invokations to the methods to be thread-safe, then make them `synchronized` – Bozho Jan 16 '11 at 22:26
  • Great, that answered the second question I was about to ask :) Thanks :) – jurchiks Jan 17 '11 at 09:56
  • How do I instantiate the main class in enum or when I need to throw an exception on getInstance()? – jurchiks Jan 17 '11 at 18:49
  • you don't instantiate nothing. You just refer to EnumClass.INSTANCE, it all happens automatically – Bozho Jan 17 '11 at 19:36
5

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.

dogbane
  • 266,786
  • 75
  • 396
  • 414
  • Why Sample 1 doesn't use lazy initialization? I think it is using since there is only one instance, and one initialization is made. – Sam003 May 29 '15 at 16:47
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.

Uri
  • 88,451
  • 51
  • 221
  • 321
  • Well, the class I want to instantiate contains 2 Map objects with possibly lots of data, two methods each for one Map to get value using key (and populate the value if it's null) and two methods that access the database (first to populate the value of a selected key, second to insert/update/delete data from database using existing data). Not counting getters/setters here. Do you think it shouldn't be a singleton? – jurchiks Jan 16 '11 at 16:06
  • I'm not sure if you're getting the core of what I'm suggesting. Let's say that you encapsulated everything you just described as an interface and corresponding class named DBLookupService and DBLookupServiceImpl. To classes that use LookupService, it does not matter where it came from - it just matters that they get an instance of LookupService. This also makes it much easier to test. – Uri Jan 16 '11 at 16:26
  • As to whether it should be singleton - probably, but you could think of multi-core optimized code in which you use multiple instances (e.g., if you could divide the data meaningfully). But my point is that you should do everything to avoid calls to that getInstance() from the code that uses the service. This will make testing and future changes much much easier. – Uri Jan 16 '11 at 16:28
2

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.

Sibbo
  • 3,796
  • 2
  • 23
  • 41