Singleton in Java

When it comes to singleton, it is one of the most frequently asked Java question. There are multiple ways to ensure singleton behavior in multi-threaded environment like

    • Making a variable public static final
    • Making a synchronized getInstance method
    • Double checked getInstance method
    • Using Enums

Lets understand pros and cons for each one of them in detail:

Making a variable public static final

This is one of the most easiest way to make a class singleton. What you all need to do is to make the constructor of the class private and declare one variable of the class as public static final and define the variable then and there only.

Consider we have a class SessionFactory and we need to make it singleton.Hence, we will be required to write the below snippet to make it singleton

class SessionFactory{

// Eager loading of Singleton instance
public static final SessionFactory instance = new SessionFactory();

private SessionFactory(){

//do Initializing stuff here

}

}

 

 

Advantages
Simple Implementation
Thread Safe as the variable will only be initialized once during class load and hence no issues even if multiple threads accessing it.

 

Disadvantages
Eager Loading as the instance will be created and loaded even if the instance is not required for the complete application to run
Fails in case class implements Clonable marker interface or Serializable marker interface. In first case, it fails if a program create a clone of the object and in case of serializable it fails when a program tries to serialize and then deserialize it. It also fails in case of reflection where even private constructors can be accessed to create the instance.

By making getInstance method synchronized

The other way to ensure singleton behaviour is to make the constructor of the class private so that no one else can access it and then make a getInstance method to return the instance of the method only when no instance has been created to yet. This implementation has a plus point over the previous implementation that in this case lazy loading will happen and the instance of the singleton class will only created when asked for.

 

class SessionFactory{

private static volatile SessionFactory instance;

private SessionFactory(){
//do Initializing stuff here
}

// Lazy loading of instance of singleton class
public static synchronized SessionFactory getInstance(){
    if(instance == null)
       instance = new SessionFactory();
    return instance;
}

}

 

Advantages
It will follow lazy loading and hence the instance of the object will only be created when there is a call made to the get Instance method.
Thread Safe as at a time only one thread will be able to access the synchronized function and will be able to create the instance

 

Disadvantages
Very slow as only thread will be able to access the function getInstance at a time even after the instance will be created as the complete function is synchronized.
As above this one also fails in case of Clonable, Serializable and Reflection.

Double checked Singleton

This is a similar one as above, but it will overcome the issue where in only one thread was able to access the getInstance function even when the instance was created. So, in this case, instead of making the complete function synchronized, it will only make the required block synchronized. There will be two checks to ensure no instance has been created yet before creating a new instance. One of this check is outside synchronized block, which will ensure that threads get into synchronized block only when there is no instance created and remaning piece of code ( to return the instance of the class ) can be executed by multiple threads at once.

 

class SessionFactory{

private static volatile SessionFactory instance;

private SessionFactory(){
//do Initializing stuff here
}

// Lazy loading of instance of singleton class
public static SessionFactory getInstance(){
    if(instance == null) {
       // Till this point as there was no synchronized check,
       // multiple threads can reach and wait because of 
       // synchronized statement next to it.
       synchronized(SessionFactory.class) {
           // Though only one thread can reach here at a time, but as 
           // multiple threads could be waiting post "if" check above, 
           // all those waiting threads can enter this synchronized block
           // one at a time and can create instances leading to multiple instances.
           // To avoid this, one more check is required here to ensure no other 
           // instance has been created yet.
           if(instance == null) {
               instance = new SessionFactory();
           }
       }
    return instance;
}

}

 

Advantages
As above, it will also follow lazy loading and hence the instance of the object will only be created when there is a call made to the get Instance method.
Thread Safe as at a time only one thread will be able to access the synchronized block and will be able to create the instance

 

Disadvantages
As above this one also fails in case of Clonable, Serializable and Reflection.

Till now, in all the possible ways shared above, all fail in case of Clonable, Serializable and Reflection. So, before we move on to the next way of Singleton. Lets discuss how we can prevent all these ways to be failing in these specific cases.

1. Clonable – One of the obvious option to this one is not to implement Clonable interface to the singleton class. But if there is a requirement to do so, override the clone method to return an exception as cloning of singleton object is not valid option.

2. Serializable – The other scenario is when the singleton class is Serializable. Good thing is JAVA provides an option to implement a readResolve method in the class that is serializable. Whenever an object will be deserialized, readResolve will be called to resolve any issues or conflicts that developer might want to fix at time of deserialization before giving the instance back to the calling statement of readObject. Hence, you can simply implement this function in Singleton class and can update current instance from the one that has been prepared during deserialization. The code snippet for the same would look like this.

class SessionFactory implements Serializable{

static final long serialVersionUID = 1L;

private static volatile SessionFactory instance;

private SessionFactory(){
//do Initializing stuff here
}

public static SessionFactory getInstance(){
    if(instance == null) {
       synchronized(SessionFactory.class) {
           if(instance == null) {
               instance = new SessionFactory();
           }
       }
    return instance;
}

// Function to ensure the singleton behaviour during deserialization.
private Object readResolve()  {
    return instance;
}

}

 
3. Reflection: As we know that even private constructor can be called using reflection. There are two ways to ensure singleton behavior during reflection.

a. One way is by checking inside constructor if there is already an instance of the class. If yes, then throw exception.

b. Another way is to restrict all reflection calls to constructor by making another check inside the constructor class

 

class SessionFactory{

private static volatile SessionFactory instance;

private SessionFactory(){
 Class currentClass= sun.reflect.Reflection.getCallerClass(1);
 Class callingClass = sun.reflect.Reflection.getCallerClass(3);
 if (self != caller)
 throw new java.lang.IllegalAccessError();

//do Initializing stuff here
}

public static SessionFactory getInstance(){
    if(instance == null) {
       synchronized(SessionFactory.class) {
           if(instance == null) {
               instance = new SessionFactory();
           }
       }
    return instance;
}

}

Using Enums

The last and the best way to implement Singleton is using enums. Also, any of the above discussed issues will not come in case of singleton.

Clonable: Enums are not clonable as they are created to ensure single instance of each value,

Serializable:  Enums are inheritably serializable and they do not serialize the way other Serialzable object are serialized. Find out more about it at official documentation

Reflection:  This is also not an issue as even if you use reflection functions to retrieve enum variable, they will be considered as constants and hence the same value will be returned everytime.

The code snippet will look like below:

class SessionFactory{

public enum SessionFactoryEnum{
    INSTANCE;
    int data;
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data= data;
    }
}

That’s all from Singleton perspective. Appreciate your suggestions or if you want anything to be added in this article.

One thought on “Singleton in Java”

Leave a Reply

Your email address will not be published. Required fields are marked *