Singleton design pattern in Java – with examples

In order to ace your programming game, you should be able to write reusable code. Code re-usability is an important aspect of good programming practice. Design patterns help us follow such best practices. Singleton is most used design pattern. Most of us use it knowingly or unknowingly on daily basis. Sometimes we don’t realize because we use many different frameworks, that use them internally. For eg: Spring framework. So let's get started with understanding this pattern. This pattern is the easiest one to learn!!! Lets learn Singleton design pattern using Java.

What is a Singleton design pattern?

Reading the name of this pattern we can get a rough idea of what the pattern is all about, don’t we? Yes, it has something to do with single or unique instance of a class. Which means this design pattern helps us create a single instance of a particular class. As a result, we can say this as a pattern which enables us to reuse the same object. As this deals with creation of object it is a type of creational design pattern.

Now, one would think why do we need only a single instance of any particular class? Let us consider a scenario where you have an application, which requires a database connection. Now, there can be an approach where, you create a new database connection whenever your service needs it. But, if you have multiple such services, then, creating a new connection for each of them, can be a very costly operation. Which may eventually lead to many problems.

Thus having a single instance for the connection is beneficial. We can use the same connection to access the database as and when we want to. There are several such examples like Java Run-time class which also implements a singleton pattern to avoid unnecessary object creation. They also facilitate reuse of the object.

Where to use Singleton pattern

This pattern can be used in following cases: 

  • Multi threaded Database applications
  • Want to limit the number of objects created in an application to save memory 
    • This can be achieved by adapting getInstance() method we can create more than one but limited objects, eg some time we may need more than 1 instance or new instance after every 100 usage
  • Utility, service classes or every class other than models can be a singleton class 

How does Singleton pattern work?

The main motto of this pattern is to "define a class that has only one instance, but has a global point of access to the instance". That means we create class in such a way that we have one instance and every time we need class instance we use same instance without creating new.

Well, how can we restrict a class to have only one instance? Because the default behavior of any constructor of a class is to provide a new instance on initialization. There are several ways in Java by which we can achieve the motto of this pattern. But all of them are based on the following basic ideas: 

  1. A private constructor to prevent others from instantiating the class : A private constructor cannot be accessed from outside the class. Thus, we cannot create an instance by invoking a constructor. 
  2. Then create the instance of the class either during class loading in a static field/block, or on-demand in a static method.
    • It is better to first check whether the instance exists or not and create a new one only if it doesn’t exist.
  3. Make this instance available publicly. Means create way for all other parts of the application to access this instance. 

The following UML can show you the basic implementation of Singleton pattern.

singleton design pattern
Singleton pattern UML

Implementation of Singleton design pattern in Java

As mentioned above Singleton pattern can be implemented in various ways. These depend on the requirement of your code.

  1. Default or Eager initialized of Singleton pattern
  2. Eager initialized Singleton with static block
  3. Lazily initialized Singleton pattern
  4. Lazily Initialized Inner Class Singleton
  5. Synchronized Singleton with single check
  6. Synchronized Singleton with double check
  7. Protection against reflection

Let us see the implementation of some of them below:

Default or Eager initialized of Singleton pattern

As per the explanation above we have a class with a private constructor so that it cannot be accessed from outside the class. And a public method "getInstance()", which can be used to access the instance of our class. Then we have our main application which will call the print method using the existing instance.

package main.java.creational.singleton;
public class Singleton {

//create an object of Singleton
private static Singleton singleton = new Singleton();

//make the constructor private
private Singleton(){}

//Get the only object available
public static Singleton getInstance(){

return singleton;

}

public void print(){

System.out.println("Hello World!");

}

}
package main.java.creational.singleton;
public class Application {

public static void main(String[] args) {

Singleton singleton = Singleton.getInstance();
singleton.print();

}

}

//OUTPUT:
Hello World!

Eager initialized Singleton with static block

There is another way to implement eagerly initialized singleton, by using a static block to create instance. The static block is executed only once at the time of class loading. The advantage of this method is that initialization logic or exceptions handling is done in the static block.

package main.java.creational.singleton;

public class EagerStaticBlockSingleton {

	private static final EagerStaticBlockSingleton instance;

	private EagerStaticBlockSingleton() {
	}

	static {
			instance = new EagerStaticBlockSingleton();
		}

	public static EagerStaticBlockSingleton getInstance() {
		return instance;
	}
}

Lazily initialized Singleton pattern

Let us first understand the meaning of Lazy initialization. Lazy initialization means the delay in initializing something until it is needed for the first time. Which in our context means that, a class is not initialized unless and until its instance is not needed. [for more details wiki]

This implementation first checks whether there already exists an instance of the class. If it is present then the same instance is returned. Otherwise a new instance is created and then returned.

package main.java.creational.singleton;

public class LazySingleton {

	 private static LazySingleton instance;

	    private LazySingleton() {}

	    public static LazySingleton getInstance() {
	        if(instance == null) {
	            instance = new LazySingleton();
	        }
	        return instance;
	    }
}

Lazily Initialized Inner Class Singleton

This way of implementation contains an inner class. This inner class is responsible to create a new instance. But this inner class is loaded only when the get instance is called, and hence lazy initialization is achieved. 

package main.java.creational.singleton;

public class LazyInitInnerClassSingleton {

	private LazyInitInnerClassSingleton() {}

    /** This inner class is loaded only after getInstance() is called for the first time. */
    private static class SingletonHelper {
        private static final LazyInitInnerClassSingleton instance = new LazyInitInnerClassSingleton();
    }

    public static LazyInitInnerClassSingleton getInstance() {
        return SingletonHelper.instance;
    }
 }

Important point here is , the getInstance() method by default is not thread safe. Means in multi threaded environment this may not work as expected. There are two ways to handle it. Lets see both ways with differences.

Synchronized Singleton with single check

We read that the getInstance() method is not thread safe. Now, from the above example let's say we do not have a instance yet. Two threads enter getInstance() method simultaneously. Eventually, the if(instance == null) will evaluate to true for both the threads . Thus, they end up creating an instance for each of the thread. 

Hence, using synchronized keyword for getInstance() makes sure that one thread enters getInstance() at a time and executes it. 

Given below you can see 2 different ways of using synchronized keyword.

  1. Make synchronized method : we can create the method as synchronizes so only one thread will enter and create instance if required
  2. Adding synchronized block : we can add synchronized block and allow only one thread at a time
package main.java.creational.singleton;

public class SynchronizedSingleton

private static SynchronizedSingleton instance;

private SynchronizedSingleton() { }

public static synchronized SynchronizedSingleton getInstance(){

if(instance == null) {

instance = new SynchronizedSingleton();

}

return instance;

}

}
package main.java.creational.singleton;

public class SynchronizedSingleton

private static SynchronizedSingleton instance;

private SynchronizedSingleton() { }

public static SynchronizedSingleton getInstance() {

synchronized (SynchronizedSingleton.class){

if(instance == null) {

instance = new SynchronizedSingleton();

}

}

return instance;

}

}

As we know adding synchronize to method will allow only one thread at a time. So all other threads have to wait even if the instance is present. This will affect the performance. Don't worry there is solution for this, Lets see how to improve it.

Synchronized Singleton with double check

Now the problem is thread is waiting even if the instance is present.Why to keep waiting if the instance is already created. All the thread can use it simultaneously without waiting.

so we can add condition out side the synchronized block, if the instance is present just use it without going into synchronized block.

package main.java.creational.singleton;

public class SynchronizedDoubleCheckSingleton {
	
    private static volatile SynchronizedDoubleCheckSingleton instance;

    private SynchronizedDoubleCheckSingleton() {}

    public static SynchronizedDoubleCheckSingleton getInstance() {
        if(instance == null) {
            synchronized (SynchronizedDoubleCheckSingleton.class) {
                // double-check
                if(instance == null) {
                    instance = new SynchronizedDoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

In this section, we have added a check if(instance == null) twice. You might be wondering why whave doble check can't just have one? No we can not have only one check.

This is important as because, if the two threads enter the method simultaneously, Both will evaluate to true. Further the threads will enter the synchronous block one by one. If there is no double-check then both will create instance one after another.

Thus, the second check avoids this scenario. Another point that you may notice in the code is the key word volatile. It prevents compilers from doing their own optimizations, eventually helping the singleton work correctly. Find more about volatile here

Protection against reflection

Reflection is a set of APIs in java. These are really powerful APIs to access a class or to instantiate it. These can come into our way of achieving Singleton pattern in our implementation. Let us see how. This is our class to be instantiated,

package main.java.creational.singleton;

public class SingletonReflection {
	
	private static SingletonReflection singleton = new SingletonReflection();
	 
	private SingletonReflection(){}

	public static SingletonReflection getInstance(){
	    return singleton;
	}
}

Note that we have a private constructor and a public method to access the instance. So far so good!! Now, let us see how the use of Reflection comes in the way of making the class Singleton.

package main.java.creational.singleton;
import java.lang.reflect.Constructor;

public class Application {

  public static void main(String[] args) {

    SingletonReflection singleton = SingletonReflection.getInstance();
    SingletonReflection reflection = null;

    try {
      Constructor[] constructors = SingletonReflection.class.getDeclaredConstructors();
      for (Constructor constructor : constructors) {
        constructor.setAccessible(true);
        reflection = (SingletonReflection) constructor.newInstance();
      }
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }

    System.out.println("singleton Instance: " + singleton.hashCode());
    System.out.println("reflection Instance: " + reflection.hashCode());
  }
}

//OUTPUT:
singleton Instance: 366712642x
reflection Instance: 1829164700

In the output you can see two separate instances of our class are created. The constructor.newInstance() method from reflection APIs makes it possible to create a new instance even if the constructor is privatef. What can we do to avoid this? We can simply throw an exception in our constructor. If it is called when the instance of the class already exists it will throw this exception.

package main.java.creational.singleton;

public class SingletonReflection {
 
  private static SingletonReflection singleton = new SingletonReflection();
  
  private SingletonReflection(){
      if(singleton != null) {
             throw new IllegalStateException("Singleton already initialized");
      }
  }

  public static SingletonReflection getInstance(){
       return singleton;
  }
}

  Benefits

  • Limits the objects creations
  • Reduces the memory required
  • Reduces garbage collection
  • Helps in Lazy initialization. That means, an object is not created until we need it and call the getInstance() method
  • Saves memory as the instances are reused 

Limitations

  • Same object is shared hence the object must be immutable
  • We can not have class level variables
    • If we use they will be overridden by other client
  • Extra code need to write for making it singleton this increases complexity
  • The getInstance() method is not thread safe, but can be overcome by using synchronized keyword

Fast track reading

  • Type of Creational design pattern 
  • Simplest and most used type of design pattern 
  • Restrict the instantiation of a class and ensures that only one instance of the class exists at a time. 
  • Steps to implement: private constructor, instantiate in itself , Provide static method to access the instance
  • Encapsulates "just-in-time initialization" or "initialization on first use". 
  • Useful in Lazy initialization
  • 7 ways to implement

2 comments

    1. Yes, we can update the object of singleton class. However it is not recommended to update as it is shared between the classes who are using the singleton object. In specific and rare cases we can update the object. For example, in the section Lazily initialized Singleton pattern we update object in getInstance() method. Or the case where we need counter for access count we can update counter variable

      public class Singleton {
      private static Singleton singleton = new Singleton();
      private static long counter=0;

      private Singleton() {}

      public static Singleton getInstance() {
      counter= counter+1:
      return instance;
      }
      }

Leave a Reply

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