Singleton Design Pattern in Java

Singleton Design Pattern in Java is used to restrict the instantiation of a class of which we want to create not more than one instance, that can also be utilized by any other classes.

  • Because class instance creates only one time, it results in memory saving.
  • It is mostly used in multi-threaded applications, logging, thread pool, configuration settings, caching, etc.

Singleton Design Pattern in Java

Implementation of Singleton Pattern : 

  • Declare a private constructor to prevent instantiation of a singleton class from other classes.
  • Create a private static instance of that class so that it gets memory only once.
  • Create a public static getInstance() method that returns an instance of the class and offers the global point of access to the Singleton object.

Let’s check various approach to create Singleton objects using Java Programming :

 

1. Eager initialization

In this approach, the class instance is created only at the time of class loading.

public class SingletonClass{

  private SingletonClass() {}
  
  //instance of a class at the time of class loading
  private static SingletonClass instance= new SingletonClass();

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

But it has one major drawback that it always creates the class instance whether it is required or not by the user which leads to resource wastage.

2. Static block initialization

It is similar to Eager initialization, the only difference is that class instance is created within a static block which only executed once at the time of class loading. And also in static block, we can handle the exceptions.
It also creates class instance whether it is required or not by the user like in Eager initialization.

public class SingletonClass{

  private SingletonClass() {}
  
  //instance of a class at the time of class loading
  private static SingletonClass instance;

  //static block in which instance of class created and also handle exception.
  static{
    try{

      instance= new SingletonClass();
    }catch(Exception e)
    {
      throw e;
    }
  }

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

But in this also, the problem of resource wastage still occurs as it also creates class instance whether it is required or not.

3. Lazy Initialization

This overcomes the drawback of both eager and static block initialization as it first checks if class instance is required or not and then allows to create the instance.
It first checks if the instance is null or not. If null then it allows us to create an instance and return its reference else return the previously created instance reference.

public class LazilySingletonClass{

  private LazilySingletonClass() {}
  
  //instance of class at time of class loading
  private static LazilySingletonClass instance;

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

But a major drawback in this is the multi-threaded environment that can destroy singleton property because if more than one thread simultaneously come to getInstance() method and check if instance==null, then because all threads having instance=null leads to creating more than one instance variable and resulting in the break of the singleton property.

4. Thread Safe Singleton

To resolve the problem due to a multi-threaded environment, a synchronized keyword is used with getInstance() method to prevent the race condition. A synchronized block is used in Thread Safe Singleton to ensure that at a time, only one thread can execute in getInstance() method. So, to overcome the multi-threaded environment, we create the instance variable in a synchronized block.

public class ThreadSafeSingletonClass{

  private ThreadSafeSingletonClass() {}
  
  //instance of class at time of class loading
  private static ThreadSafeSingletonClass instance;

  //synchronized block
  public static synchronized ThreadSafeSingletonClass getInstance()
  {
    if(instance== null)
    {
      instance= new ThreadSafeSingletonClass();
    }
    return instance;
  } 
}

But there is one problem that arises, that due to synchronized getInstance() method, there would be slow processing as not more than one thread can’t access concurrently.

5. Lazy initialization with Double-check locking

In this, the problem of slow processing due to the synchronized method is resolved. Here we double-check the initialization of the class instance variable. In this process, getInstance() method is not synchronized but the initialization component wrap within the synchronized block. For the first time, it may affect performance.

Let’s say two threads  T1, T2 enters the getInstance() method concurrently and both get inside if statement as having instance==null. Then when the first thread T1 goes inside the synchronized block to create a class instance, the other thread T2 blocked outside till T1 gets out of the synchronized block, and then T2 allows to go inside the synchronized block to create an instance.

public class DoubleCheckLockingSingletonClass{

  private DoubleCheckLockingSingletonClass() {}
  
  //instance of class at time of class loading
  private static DoubleCheckLockingSingletonClass instance;

  public static synchronized DoubleCheckLockingSingletonClass getInstance()
  {
    if(instance== null)
    {
                        //synchronized block
      synchronized(DoubleCheckLocking.class)
      {
        if(instance== null)
        {
          instance= new DoubleCheckLocking();
        }
      }
    }
    return instance;
  } 
}

6. Bill Pugh Singleton Implementation

This is also said as Lazily Initialized Inner Class Singleton implementation. This is considered as an efficient approach to create Singleton Design Patterns. Bill Pugh proposed a methodology of static inner class to lazily create a Singleton instance.

Until we call the getInstance() method for the first time, the inner class will not be loaded and hence class instance will not be created. There would be no impact on the inner class if Singleton class is loaded till getInstance() method called.
The major advantage of using a static inner class is that we no more need a synchronized block.

public class LazyInnerSingletonClass{

  private LazyInnerSingletonClass() {}


  //instance class is loaded only after getInstance() method is called
  private static class BillPughSingletonClass
  {
    private static final LazyInnerSingletonClass instance= new LazyInnerSingletonClass();
  }


  public static LazyInnerSingletonClass getInstance()
  {
    return BillPughSingletonClass.instance;
  } 
}

You can additionally learn :

Validate identifier using Regular Expression in Java

Leave a Reply