Singletons in Java

Singletons in Java

So what is a singleton? In a simpleton’s language, a singleton is a class that will be instantiated only once. This essentially means that there will be only one instance of the Java class in the Java Virtual Machine (JVM). The singleton was initially proposed by the famous Gang of Four in their design patterns. It comes under the category of creational design patterns.

The singleton design pattern is used in Logging objects, Java Runtime, etc. Good candidates are often the objects which are heavy to initialise. Can you think of any other examples where the singleton design pattern would be useful?

The recipe for making a singleton is quite simple! You would just need:

  • a static member of the class which is an instance of the singleton class
  • a private constructor which prevents initialisation of the class
  • a public static member which others can use to get an instance of your singleton class.

Enough talk! Let us start with some code which will help us understand the various implementations and their pros and cons.

Lazy initialisation

Let us be lazy first and see what the Lazy implementation is,

public class Singleton {
    // static member of the class
    private static Singleton singletonObject;
    // The private constructor
    private Singleton() {}
    // Public static member for access outside the class
    public static Singleton getSingletonInstance() {
        if (singletonObject == null) {
            singletonObject = new Singleton();
        }
        return singletonObject;
    }
}

Whenever a person decides to call the method getSingletonInstance() for the first time, the object singletonObject is null and the if condition makes sure that the object is initialised and then returned. However, when the subsequent calls are made the object does not have to be initialised anymore and is returned as is. This implementation is called the Lazy implementation because the instance is not initialised until we first need it. But, as you all know, being lazy is not a good thing every time! This implementation comes at the cost of the null check every time. You should also note that this approach is not thread safe.

Eager initialisation

Well, being lazy never helped out anyone. Let us try being eager now!

public class Singleton {
    // static member of the class
    private static final Singleton singletonObject = new Singleton();
    // The private constructor
    private Singleton() {}
    // Public static member for access outside the class
    public static Singleton getSingletonInstance() {
        return singletonObject;
    }
}

This implementation makes sure the object is initialized only once when the class is loaded. Notice that we have initialized the variable at the very beginning of the class and not inside a function. However, being eager comes at the cost where this object is created even if the client application may not need it. In other words, if the object is heavy to create and it is not used after being initialized, then it is a waste of CPU resources.

For the above methods, we can verify the creation of only a single instance by printing the object hashcodes and comparing them. However, these methods are not “thread-safe” and often return different instances when we use threading. This can be solved by adding the synchronized keyword to our getSingletonInstance() method.

public class Singleton {
    // static member of the class
    private static final Singleton singletonObject;
    // The private constructor
    private Singleton() {}
    // Public static member for access outside the class
    public synchronized static Singleton getSingletonInstance() {
        if (singletonObject == null) {
            singletonObject = new Singleton();
        }
        return singletonObject;
    }
}

Now, this approach will prevent the case where two threads might try to create an instance of the “Singleton” simultaneously using the locking mechanism. However, there are two important problems with this approach:

  • Decreased performance due to the synchronized keyword.
  • Unnecessary synchronization even after the object has been initialized once which again decreases the performance.

This problem can be solved by using the double checking mechanism. This approach makes sure that the minimum number of threads are in the waiting queue for initialisation. It is also ensured that it occurs only for the first time, i.e., when the object has not been initialised yet.

public class Singleton {
    private static final Singleton singleton;
	private Singleton() {};
    public static Singleton getSingletonInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

Bill Pugh Singleton

public class Singleton {
  private Singleton() {}
  // Inner class to provide instance of class
  private static class BillPughSingleton {
    private static final Singleton INSTANCE = new Singleton();
  }
  public static Singleton getSingletonInstance() {
    return BillPughSingleton.INSTANCE;
  }
}

When the singleton class is loaded, the inner static class is not loaded and thus, does not create the object when loading the class preventing eager initialization. The inner static class is created only when getSingletonInstance() method is called, which endorses the lazy initialization method. The use of the static class also makes sure that the implementation is thread-safe. This method can be destroyed by reflection but that’s a story for another day!

The Singleton is an awesome design pattern but it should be used cautiously. This is because when you make a class a singleton, it becomes very hard to test it. You can read more about this in this thread.

That is all folks! See you soon 😀

No Comments

Post A Comment