Android Architecture

Perfect Singleton in Java

In this post, I will tell you how to make the perfect Singleton class in Java? Firstly, we will describe the is Singleton Design Pattern. Further, I tell you possible ways to create Singleton class. After reading this post you will able to create a perfect Singleton in Java.

Design Pattern is addressed to a common software problem. Singleton design patterns are popular among them, It’s one of the Creational Design Patterns in Java.

What is the Singleton Design Pattern?

The main object of the singleton class is to control instance or object creation, limiting the number of objects to only one. This design pattern allows only one way (entry point) to create a new instance of the class. Let’s read the below statement that will give you more clarity.

  • Singleton design pattern is one of the simplest design patterns, It’s based on Creational Design Pattern
  • Singleton class is responsible to instantiate itself, to make sure it creates only one instance.
  • It provides a global point of access to that object.
  • Same instance can be used everywhere.

It seems to be a very simple design pattern. But when it comes to implementation, it comes with a lot of implementation concerns. The implementation of Singleton pattern has always been a controversial topic among developers. Here, we are going to discuss how to create a Singleton class that fulfills its purpose :

Purpose of Singleton

Restrict the instantiation of a class and ensures that only one instance of the class exists in JVM.

Let’s take one class which does not contain attribute or any state(Such as Logger, Validator, Firebase). Such case we want to create one object and use it multiple times. If we create multiple objects of same data class is wasting memory, degrading performance.

When to use Singleton?

  • A class which does not contain attribute or any state. For Example, Conversion class, Validation class
  • For a class which we want to create only a single object or instance(Logger, Database, etc).
  • Some more examples
    • Singleton pattern is used in Abstract, Factory, Builder, and Prototype and Facade, etc.
    • It used in configuration classes
    • Whenever we access resources in shared mode
    • Used also drivers objects, caching, logging and thread pool

Method of creating Singleton class in Java

Let’s come to the singleton creation methods. In this section, we will learn different approaches to Singleton design pattern implementation and concern with the implementation.

  • Eager initialization
  • Lazy initialization

1. Eager initialization

Eager initialization is the easiest method to create a Singleton class. In this method instance of Singleton class is created at the time of class loading.

In this initialization, we make constructor as private. So you are not allowed to other class to create a new instance of the class.

For accessing this class we create one public static method to provide a single entry point. (commonly named as for getInstance()).

/**
 * Eager Initialized Singleton Example
 */
public class EagerInitializedSingletonExample {

  private static volatile EagerInitializedSingletonExample instance =
      new EagerInitializedSingletonExample();

  //private constructor.
  private EagerInitializedSingletonExample() {
  }

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

This approach has one setback. In Eager initialization, Instance is created at the time of class loading. Other words you can say class instance is created even application might not be using it. This might be a considerable issue if you are creating a database connection or creating a socket. This may cause a memory leak problem.

2. Lazy initialization

To overcome problem eager initialization, We will create new instance of the class when needed. It just opposite of eager initialization. Here we initialized new instance of the class in getInstance() methods itself. Inside this method, we will check is there any instance of that class is already created? if yes then will return old instance if not then it creates a new instance of the class and returns them. This approach is known as Lazy initialization.

/**
 * Lazy Initialized Singleton Example
 */
public class LazyInitializedSingletonExample {
  private static LazyInitializedSingletonExample instance;

  private LazyInitializedSingletonExample() {
  }  //private constructor.

  public static LazyInitializedSingletonExample getInstance() {
    if (instance == null) {
      //if there is no instance available... create new one
      instance = new LazyInitializedSingletonExample();
    }

    return instance;
  }
}

Test your Singleton class

Now, your singleton class created. Now you have to ensure your getInstance() methods are always returning the same instance(always return the same instance is the primary goal to achieve singleton design pattern ).

In Java, if two objects are same then their hash key should be same or equal. Let’s test the above implementation, If the Singleton is correctly implemented than below code should return the same hash key.

/**
 * Test your singleton
 */
public class SingletonTester {

  public static void main(String[] args) {
    //Instance 1
    LazyInitializedSingletonExample instance1 = LazyInitializedSingletonExample.getInstance();

    //Instance 2
    LazyInitializedSingletonExample instance2 = LazyInitializedSingletonExample.getInstance();

    //now lets check the hash key.
    System.out.println("Instance 1 hash:" + instance1.hashCode());
    System.out.println("Instance 2 hash:" + instance2.hashCode());
  }
}
Here is output
Instance 1 hash:1735600054
Instance 2 hash:1735600054

Process finished with exit code 0

You can see here, instances 1 & 2 are having the same hash code. So, that means the above code will make the perfect Singleton. Right??? the answer is No.

Make Singleton reflection proof

The above Singleton class is not reflection proof. By using reflection you can create more than one instance. For more about that read java official doc Java Reflection API.

Basically, Reflection is a process that has the ability to examine or modify the runtime behavior of applications running in the JVM.

Let’s run below code
/**
 * Test your singleton
 */
public class SingletonTester {

  public static void main(String[] args) {
    
    //Create the 1st instance
    LazyInitializedSingletonExample instance1 = LazyInitializedSingletonExample.getInstance();

    //Create 2nd instance using Java Reflection API.
    LazyInitializedSingletonExample instance2 = null;
    try {
      Class<LazyInitializedSingletonExample> clazz = LazyInitializedSingletonExample.class;
      Constructor<LazyInitializedSingletonExample> cons = clazz.getDeclaredConstructor();
      cons.setAccessible(true);
      instance2 = cons.newInstance();
    } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e) {
      e.printStackTrace();
    }

    //now lets check the hash key.
    System.out.println("Instance 1 hash:" + instance1.hashCode());
    System.out.println("Instance 2 hash:" + instance2.hashCode());
  }
}
Output is :
Instance 1 hash:1735600054
Instance 2 hash:21685669

Process finished with exit code 0

In this case, both instances have the different hash code. That means your Singleton class failed this test.

Solution

For making reflection proof Singleton, You have to throw a run time exception in constructor is already initialized and some other class trying to initialize again. Let’s update the LazyInitializedSingletonExample.java

/**
 * Lazy Initialized Singleton Example
 */
public class LazyInitializedSingletonExample {
  private static LazyInitializedSingletonExample instance;

  //private constructor.
  private LazyInitializedSingletonExample() {
    if (instance != null) {
      throw new RuntimeException(
          "Use getInstance() method to get the single instance of this class.");
    }
  }

  public static LazyInitializedSingletonExample getInstance() {
    if (instance == null) {
      //if there is no instance available... create new one
      instance = new LazyInitializedSingletonExample();
    }

    return instance;
  }
}

Make Singleton thread-safe

Your singleton class should be thread-safe. Suppose two threads try to initialize as Singleton class at the same time. Let’s see below example.

/**
 * Test your singleton
 */
public class SingletonTester {

  public static void main(String[] args) {

    //Thread 1
    Thread t1 = new Thread(new Runnable() {
      @Override
      public void run() {
        LazyInitializedSingletonExample instance1 = LazyInitializedSingletonExample.getInstance();
        System.out.println("Instance 1 hash:" + instance1.hashCode());
      }
    });

    //Thread 2
    Thread t2 = new Thread(new Runnable() {
      @Override
      public void run() {
        LazyInitializedSingletonExample instance2 = LazyInitializedSingletonExample.getInstance();
        System.out.println("Instance 2 hash:" + instance2.hashCode());
      }
    });

    //start both the threads
    t1.start();
    t2.start();
  }

If you run the above code many times, sometimes both the threads creates different instances like below.

Instance 2 hash:418579292
Instance 1 hash:150854385

Process finished with exit code 0

That means this Singleton class is not thread-safe. In this case, both threads calling getInstance() methods at the same time, instance == null condition will return for both the thread. That by the same instance of the same class will be created. This will break the singleton principle completely.

Solution :
  • Using synchronized
  •  Double-Check Locking
  • Use volatile Keyword
1. Using synchronized

Let’s make getInstance() method synchronized.

/**
 * Lazy Initialized Singleton Example
 */
public class LazyInitializedSingletonExample {
  private static LazyInitializedSingletonExample instance;

  //private constructor.
  private LazyInitializedSingletonExample() {
    if (instance != null) {
      throw new RuntimeException(
          "Use getInstance() method to get the single instance of this class.");
    }
  }

  public synchronized static LazyInitializedSingletonExample getInstance() {
    if (instance == null) {
      //if there is no instance available... create new one
      instance = new LazyInitializedSingletonExample();
    }

    return instance;
  }
}

So in this case, you make getInstance() method is synchronized. While we use synchronized keyword JVM will put a lock on that at the same second thread will have to wait until the getInstance() method is completed for the first thread.

Some drawback of this solution
  • Slow performance
  • synchronization is not used once the instance variable is initialized.
2. Double-Check Locking

You can make thread-safe Singleton using Double Check Locking method. In this method, we synchronized block if the instance is null. So, the synchronized block will be executed only when the instance is null.

/**
 * Lazy Initialized Singleton Example
 */
public class LazyInitializedSingletonExample {
  private static LazyInitializedSingletonExample instance;

  //private constructor.
  private LazyInitializedSingletonExample() {
    if (instance != null) {
      throw new RuntimeException(
          "Use getInstance() method to get the single instance of this class.");
    }
  }

  public static LazyInitializedSingletonExample getInstance() {
    if (instance == null) {
      //if there is no instance available... create new one
      synchronized (LazyInitializedSingletonExample.class) {   //Check for the second time.
        //if there is no instance available... create new one
        if (instance == null) instance = new LazyInitializedSingletonExample();
      }
    //  instance = new LazyInitializedSingletonExample();
    }

    return instance;
  }
}
Output is :
Instance 1 hash:271732421
Instance 2 hash:271732421

Process finished with exit code 0
3. Use volatile Keyword

The above solution is quite stable but still, Still it can break until you make an instance variable volatile. Without volatile modifier, it’s can be possible for another thread in Java to see the half initialized state of instance variable. But with volatile variable guaranteeing all the write will happen before any read of instance variable.

/**
 * Lazy Initialized Singleton Example
 */
public class LazyInitializedSingletonExample {
  private static volatile LazyInitializedSingletonExample instance;

  //private constructor.
  private LazyInitializedSingletonExample() {
    if (instance != null) {
      throw new RuntimeException(
          "Use getInstance() method to get the single instance of this class.");
    }
  }

  public static LazyInitializedSingletonExample getInstance() {
    if (instance == null) {
      //if there is no instance available... create new one
      synchronized (LazyInitializedSingletonExample.class) {   //Check for the second time.
        //if there is no instance available... create new one
        if (instance == null) instance = new LazyInitializedSingletonExample();
      }
      //  instance = new LazyInitializedSingletonExample();
    }

    return instance;
  }
}

Above singleton java example is thread-safe. Especially thread-safe singleton required in a multi-threaded application environment just like in Android Apps.

Conclusion

End of this article, you can make a singleton in java that is refection proof and thread-safe. If you want to make it serialization safe, I have written another article on that. The above implementation of the Singleton class will work perfectly. This way you can create a perfect singleton in java. Read more article on design patten

If you have any quires or suggestions, feel free put your comment below.

https://paypal.me/
droidwave?locale.x=en_GB

Leave a Reply

2000