Open In App

Java Singleton Design Pattern Practices with Examples

Improve
Improve
Like Article
Like
Save
Share
Report

In previous articles, we discussed about singleton design pattern and singleton class implementation in detail. 
In this article, we will see how we can create singleton classes. After reading this article you will be able to create your singleton class according to your requirement, which is simple and without bottlenecks. 
There are many ways this can be done in Java. All these ways differ in their implementation of the pattern, but in the end, they all achieve the same end result of a single instance. 
 

  1. Eager initialization: This is the simplest method of creating a singleton class. In this, object of class is created when it is loaded to the memory by JVM. It is done by assigning the reference of an instance directly. 
    It can be used when program will always use instance of this class, or the cost of creating the instance is not too large in terms of resources and time.
     

JAVA




// Java code to create singleton class by
// Eager Initialization
public class GFG
{
  // public instance initialized when loading the class
  private static final GFG instance = new GFG();
 
  private GFG()
  {
    // private constructor
  }
  public static GFG getInstance(){
        return instance;
    }
}


  1. Pros:
    1. Very simple to implement.
    2. May lead to resource wastage. Because instance of class is created always, whether it is required or not.
    3. CPU time is also wasted in creation of instance if it is not required.
    4. Exception handling is not possible.
  2. Using static block: This is also a sub part of Eager initialization. The only difference is object is created in a static block so that we can have access on its creation, like exception handling. In this way also, object is created at the time of class loading. 
    It can be used when there is a chance of exceptions in creating object with eager initialization. 
     

JAVA




// Java code to create singleton class
// Using Static block
public class GFG
{
  // public instance
  public static GFG instance;
 
  private GFG()
  {
    // private constructor
  }
static
  {
    // static block to initialize instance
    instance = new GFG();
  }
}


  1. Pros:
    1. Very simple to implement.
    2. No need to implement getInstance() method. Instance can be accessed directly.
    3. Exceptions can be handled in static block.
    4. May lead to resource wastage. Because instance of class is created always, whether it is required or not.
    5. CPU time is also wasted in creation of instance if it is not required.
  2. Lazy initialization: In this method, object is created only if it is needed. This may prevent resource wastage. An implementation of getInstance() method is required which return the instance. There is a null check that if object is not created then create, otherwise return previously created. To make sure that class cannot be instantiated in any other way, constructor is made final. As object is created with in a method, it ensures that object will not be created until and unless it is required. Instance is kept private so that no one can access it directly. 
    It can be used in a single threaded environment because multiple threads can break singleton property as they can access get instance method simultaneously and create multiple objects. 
     

JAVA




//Java Code to create singleton class
// With Lazy initialization
public class GFG
{
  // private instance, so that it can be
  // accessed by only by getInstance() method
  private static GFG instance;
 
  private GFG()
  {
    // private constructor
  }
 
  //method to return instance of class
  public static GFG getInstance()
  {
    if (instance == null)
    {
      // if instance is null, initialize
      instance = new GFG();
    }
    return instance;
  }
}


  1. Pros:
    1. Object is created only if it is needed. It may overcome wastage of resource and  CPU time.
    2. Exception handling is also possible in method.
    3. Every time a condition of null has to be checked.
    4. instance can’t be accessed directly.
    5. In multithreaded environment, it may break singleton property.
  2. Thread Safe Singleton: A thread safe singleton is created so that singleton property is maintained even in multithreaded environment. To make a singleton class thread safe, getInstance() method is made synchronized so that multiple threads can’t access it simultaneously.
     

JAVA




// Java program to create Thread Safe
// Singleton class
public class GFG
{
  // private instance, so that it can be
  // accessed by only by getInstance() method
  private static GFG instance;
 
  private GFG()
  {
    // private constructor
  }
 
 //synchronized method to control simultaneous access
  synchronized public static GFG getInstance()
  {
    if (instance == null)
    {
      // if instance is null, initialize
      instance = new GFG();
    }
    return instance;
  }
}


  1. Pros:
    1. Lazy initialization is possible.
    2. It is also thread safe.
    3. getInstance() method is synchronized so it causes slow performance as multiple threads can’t access it simultaneously.
  2. Lazy initialization with Double check locking: In this mechanism, we overcome the overhead problem of synchronized code. In this method, getInstance is not synchronized but the block which creates instance is synchronized so that minimum number of threads have to wait and that’s only for first time.
     

JAVA




// Java code to explain double check locking
public class GFG
{
  // private instance, so that it can be
  // accessed by only by getInstance() method
  private static GFG instance;
 
  private GFG()
  {
    // private constructor
  }
 
  public static GFG getInstance()
  {
    if (instance == null)
    {
      //synchronized block to remove overhead
      synchronized (GFG.class)
      {
        if(instance==null)
        {
          // if instance is null, initialize
          instance = new GFG();
        }
       
      }
    }
    return instance;
  }
}


  1. Pros:
    1. Lazy initialization is possible.
    2. It is also thread safe.
    3. Performance overhead gets reduced because of synchronized keyword.
    4. First time, it can affect performance.
  2. Bill Pugh Singleton Implementation: Prior to Java5, memory model had a lot of issues and above methods caused failure in certain scenarios in multithreaded environment. So, Bill Pugh suggested a concept of inner static classes to use for singleton.
     

JAVA




// Java code for Bill Pugh Singleton Implementation
public class GFG
{
 
  private GFG()
  {
    // private constructor
  }
 
  // Inner class to provide instance of class
  private static class BillPughSingleton
  {
    private static final GFG INSTANCE = new GFG();
  }
 
  public static GFG getInstance()
  {
    return BillPughSingleton.INSTANCE;
  }
}


  1. When the singleton class is loaded, inner class is not loaded and hence doesn’t create object when loading the class. Inner class is created only when getInstance() method is called. So it may seem like eager initialization but it is lazy initialization. 
    This is the most widely used approach as it doesn’t use synchronization.

 

When to use What

 

  1. Eager initialization is easy to implement but it may cause resource and CPU time wastage. Use it only if cost of initializing a class is less in terms of resources or your program will always need the instance of class.
  2. By using Static block in Eager initialization we can provide exception handling and also can control over instance.
  3. Using synchronized we can create singleton class in multi-threading environment also but it can cause slow performance, so we can use Double check locking mechanism. 
     
  4. Bill Pugh implementation is most widely used approach for singleton classes. Most developers prefer it because of its simplicity and advantages.



 



Last Updated : 31 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads