views:

311

answers:

7
+3  Q: 

Singleton in java

I just got to read the following code somewhere :

public class SingletonObjectDemo {

    private static SingletonObjectDemo singletonObject;
    // Note that the constructor is private
    private SingletonObjectDemo() {
        // Optional Code
    }
    public static SingletonObjectDemo getSingletonObject() {
        if (singletonObject == null) {
            singletonObject = new SingletonObjectDemo();
       }
       return singletonObject;
    }
}

I need to know what is the need of this part :

if (singletonObject == null) {
    singletonObject = new SingletonObjectDemo();
}

What if we do not use this part of code ? There would still be a single copy of SingletonObjectDemo, why do we need this code then ?

A: 

This code

  • is responsible for creating the first object
  • prevents from creating another
Ankit Jain
A: 

At first singletonObject is set to null. The idea behind the singleton is to initialize that object first time when someone calls getSingletonObject(). If you don't call constructor in that part the variable will always be null.

Klark
+1  A: 

The class as given doesn't create the first instance of the object until it is requested. The private static field is null until the first request, then an instance of the object is constructed and stored there. Subsequent requests return the same object.

If you remove those two lines of code, you would never actually create the initial instance, so you would always be returning null.

Donnie
+2  A: 

This class has a field SingletonObjectDemo singletonObject that holds the singleton instance. Now there are two possible strategies -

1 - You do eager initialization of the object with the declaration -

private static SingletonObjectDemo singletonObject = new SingletonObjectDemo();

This will cause your singleton object to be initialized the moment the class is loaded. The downside of this strategy is that if you have many singletons, they will all be initialized and occupying memory even when they are not needed yet.

2 - You do lazy initialization of the object i.e. initialize it when the first call to getSingletonObject() is made -

// note that this initializes the object to null by default
private static SingletonObjectDemo singletonObject;

...

if (singletonObject == null) {
        singletonObject = new SingletonObjectDemo();
    }

This saves you the memory until the singleton is really needed. The downside of this strategy is that the first invocation of the method may see slightly worse response time as it will have to initialize the obejct before returning it.

Samit G.
Thank you ! I was exactly looking for this answer.
Ishi
Also would like to add, as others have pointed out, that you should make the `getSingletonObject()` method `synchronized` with the second strategy to make it thread-safe, if running the code in a multi-threaded env. If it is not synchronized and two threads invoke the method at the same time when the object is still null, both might end up creating a new instance each.
Samit G.
Why would the class be loaded before it is needed?
Rotsor
The time that a class is loaded into the jvm is dependent on the jvm implementation. The spec itself doesn't specify when classes are loaded. This means that it is almost impossible to accurately predict when a class is loaded. I, and I think most people, assume worst case performance and prefer the second option. This way, we can guarantee that the object is not consuming memory until we need it.
Zoe Gagnon
+1  A: 

The 2 lines check whether or not the one and only singleton is created and if not they will create the singleton instance. If the instance does exist already nothing is done and it is returned. The singleton instance is created the first time it is needed on-demand, not when the application initialises.

Note that your code contains a race-condition error. When 2 threads enter concurrently, the singleton object can be allocated twice. This can be fixed by synchronizing the method like so:

public static synchronized SingletonObjectDemo getSingletonObject() {
    if (singletonObject == null) {
        singletonObject = new SingletonObjectDemo();
    }
    return singletonObject;
}

Btw, to come back to your question, the line:

private static SingletonObjectDemo singletonObject;

declares a static reference but it won't acvtually allocate an instance, the reference is set to null by the Java compiler.

rsp
+6  A: 

On lazy vs eager initialization

The if statement is an implementation of the lazy initialization technique.

A more explicit version is as follows:

private boolean firstTime = true;
private Stuff stuff;

public Stuff gimmeStuff() {
   if (firstTime) {
      firstTime = false;
      stuff = new Stuff();
   }
   return stuff;
}

What happens is that the very first time gimmeStuff() is invoked, firstTime would be true, so stuff would be initialized to new Stuff(). On subsequent invokations, firstTime would be false, so new Stuff() would no longer be called.

Thus, stuff is initialized "lazily". It's not actually initialized until the very first time it's needed.

See also


On thread safety

It needs to be said that the snippet is not thread-safe. If there are multiple threads, then in some race conditions new SingletonObjectDemo() may be invoked several times.

One solution is to make synchronized getSingletonObject() method. This does, however, have a synchronization overhead on ALL calls to getSingletonObject(). The so-called double-checked locking idiom is then used to try to remedy this, but in Java, this idiom does not actually work until J2SE 5.0 with the introduction of volatile keyword in the new memory model.

Needless to say that proper enforcement of singleton pattern isn't a trivial thing.

See also

Related questions


Effective Java 2nd Edition

Here's what the book has to say on these subjects:

Item 71: Use lazy initialization judiciously

As is the case for most optimizations, the best advice for lazy initialization is "don't do it unless you need to". Lazy initialization is a double-edged sword. It decreases the cost of initializing a class or creating an instance, at the expense of increasing the cost of accessing a lazily initialized field. Depending on what fraction of lazily initialized fields eventually require initialization, how expensive it is to initialize them, and how often each field is accessed, lazy initialization (like many "optimizations" actually harm performance).

In the presence of multiple threads, lazy initialization is tricky. If two or more threads share a lazily initialized field, it is critical that some form of synchronization be employed, or severe bugs can result.

Under most circumstances, normal initialization is preferable to lazy initialization.

Item 3: Enforce the singleton property with a private constructor or an enum type

As of release 1.5. there is a third approach to implementing singletons. Simply make an enum type with one element. [...] This approach is functionally equivalent to the public field approach, except that it's more concise, provides the serialization mechanism for free, and provides ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection-based attacks.

[...] A single-element enum type is the best way to implement a singleton.

Related questions

On enum singleton/Java implementation:

On singleton pattern merits and alternatives:

polygenelubricants
+1 in appreciation of encyclopedic detail!
Carl Smotricz
-1 for waaay overshooting the goal
Dave
+2  A: 

What if we do not use this part of code ? There would still be a single copy of SingletonObjectDemo, why do we need this code then ?

The idea is to lazy-load the singleton i.e. to load the instance only when actually needed. Why would you want to do that? Well, Bob Lee summarizes this pretty well in Lazy Loading Singletons:

In production, you typically want to eagerly load all your singletons so you catch errors early and take any performance hit up front, but in tests and during development, you only want to load what you absolutely need so as not to waste time.

But the implementation you're showing is broken, it is not thread safe and two concurrent threads could actually create two instances. The best way to make your lazy loaded singleton thread safe would be to use the Initialization on Demand Holder (IODH) idiom which is very simple and has zero synchronization overhead. Quoting Effective Java, Item 71: Use lazy initialization judiciously (emphasis is not mine):

If you need to use lazy initialization for performance on a static field, use the lazy initialization holder class idiom. This idiom (also known as the initialize-on-demand holder class idiom) exploits the guarantee that a class will not be initialized until it is used [JLS, 12.4.1]. Here’s how it looks:

// Lazy initialization holder class idiom for static fields
private static class FieldHolder {
    static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }

When the getField method is invoked for the first time, it reads FieldHolder.field for the first time, causing the FieldHolder class to get initialized. The beauty of this idiom is that the getField method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access. A modern VM will synchronize field access only to initialize the class. Once the class is initialized, the VM will patch the code so that subsequent access to the field does not involve any testing or synchronization.

See also

Pascal Thivent