Perfect Singleton in Java – AndroidWave

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  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.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 SingletonRestrict 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?Method of creating Singleton class in JavaLet’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.1. Eager initializationEager 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 initializationTo 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 classNow, 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 proofThe 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 .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 clazz = LazyInitializedSingletonExample.class;

Constructor 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.SolutionFor 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-safeYour 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 :1. Using synchronizedLet’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 solution2. 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 KeywordThe 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.ConclusionEnd 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. If you have any quires or suggestions, feel free put your comment below.

May 29, 2019

February 3, 2019

January 27, 2019Connect withI allow to create an accountWhen you login first time using a Social Login button, we collect your account public profile information shared by Social Login provider, based on your privacy settings. We also get your email address to automatically create an account for you in our website. Once your account is created, you’ll be logged-in to this account.Connect withI allow to create an accountWhen you login first time using a Social Login button, we collect your account public profile information shared by Social Login provider, based on your privacy settings. We also get your email address to automatically create an account for you in our website. Once your account is created, you’ll be logged-in to this account.PeterThanks for the interesting article, but I have a question. I’m not sure it is completely safe from instantiation with reflection. If we don’t call ‘getInstance’ method, we can create as many objects as we want using reflection. Do you know ways of avoiding this issue?21 days ago

Leave a Reply

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