Singleton design pattern in java

In this post, we will see about Singleton design pattern in java.

Singleton design pattern is one of the simplest design pattern but singleton property can be broken using multithreading, reflection, serialization etc, so you need to be careful while you create the singleton class.

Singleton design pattern restricts a class to create multiple objects so you can create only one instance of singleton class.Singleton classes are used for logging, database connections, caching and thread pool, .etc.

Singleton class

There are many ways to create singleton but it has few common steps.

    • Make constructor private: You need to make the constructor private so you can not create instance of class from outside of the class.
    • Provide static method to access object of singleton class: Create static method which will return object of singleton class.
    • Create instance of same class as public static which will be returned by static method.

Singleton

There are many ways to create Singleton class, we will see each one in detail.

Eager initialization

Eager initialization is one of the simplest ways to create singleton.Object of the class is created once class is loaded into memory.It is done by creating object of the class when we declare reference variable.

Let’s understand with the help of example:

Even if client does not need singleton object, still instance is created.If your singleton object is not resource intensive, you can still use it but in general, when you use singleton for connection pooling or database connections, it is resource intensive.

Lazy initialization

Lazy initialization is another way of creating singleton.Instead of creating object at time of variable declaration, we can create it in static method getInstance as below

Above code will work fine in case of single-threaded system but in case of multithreading, you might end up creating more than one instance of the class.

Thread safe Singleton

The easiest way to create above class thread-safe is to make getInstance method singleton as below.

Above approach will work fine and provide thread safety but there is performance cost associated with it as we have made whole method synchronized. Instead of making getInstance method, we can implement double check locking pattern.

Double check locking

Double check locking use synchronized block with extra null check to make sure only one instance is created for singleton class as below.

Why do you need double check locking? What can be problem with below code.

Let’s say Thread T1 and T2 both found instance as null.Both T1 and T2 are waiting for class level lock.T1 takes the lock and creates the instance of ThreadSafeSingletonDoubleCheck and releases the lock. T2 takes the lock now and it too creates object of singleton which violates our requirement that’s why we require double check lock here.

Bill Pugh Singleton Implementation

Bill pugh singleton implementation is one of the best way to create singleton class. It makes use of static inner class to create singleon class.

When the singleton class is loaded, inner class is not loaded and hence it doesn’t create object of Singleton class when loading the class. Inner class is created only when getInstance() method is called. So it looks like a eager initialization at first, but it is actually lazy initialization.

Create singleton using Enum

As Java Enum are global constants and loaded only once. Joshua Bloch suggested that Enum is best candidate for singleton design pattern. Please note that Java Enum does not allow lazy initialazation, so even if you do not use singleton, it will still be loaded.
Enum exmaple:

As Enum does not provide any explicit constructor, you can not create multiple instance of sinlgeton class even with reflection.

Testing singleton with Reflection

You can easily destroy singleton with the help of reflection for all above implementations excpet Enum.Reflection is powerful mechanism to instantiate the objects.
Let’s understand with the help of example:

When you run above program, you will get below output:

Hashcode of instance1: 865113938
Hashcode of instance2: 1442407170

As you can see, Hashcode of instance1 and instance2 are different, so we are able to create two instance of singleton class.

You can restrict the scenario by throwing Runtime Exception when reflection tries to create the instance of object second time as below.

When you run ReflectionSingletonTest now, you will get below output.

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.arpit.java2blog.singleton.ReflectionSingletonTest.main(ReflectionSingletonTest.java:14)
Caused by: java.lang.RuntimeException: You can not create object of singleton class twice
at org.arpit.java2blog.singleton.BillPughSingleton.(BillPughSingleton.java:10)
… 5 more
Hashcode of instance1: 1028566121
Exception in thread “main” java.lang.NullPointerException
at org.arpit.java2blog.singleton.ReflectionSingletonTest.main(ReflectionSingletonTest.java:21)

As you can see, above program throws Runtime Exception, when reflection tries to create object of singleton class twice.

Testing singleton with Serialization

When you serialize and deserialize the object of the singleton class, you should get the same object.
Let’s see if we are going to get the same object or not with the help of simple example.
Let’s first make BillPughSingleton class Serializable.

Let’s create SingletonSerializedTest to test serialization scenario.

When you run above program, you will get below output.

Hashcode of instance1: 589431969
Hashcode of instance2: 295530567

As you can see, Hashcode of instance1 and instance2 are different, so we are able to create two instances of singleton class with help of serialization.
Implement readResolve method to overcome above scenario as below.

When you run SingletonSerializedTest now, you will get below output.

Hashcode of instance1: 589431969
Hashcode of instance2: 589431969

Testing singleton with Cloning.

In case, if your singleton class implements clonable interface, you need to override clone method and throw CloneNotSupportedException from it.

Let’s create CloningSingleonTest to create cloning scenario.

When you run above program, you will get below output.

Exception in thread “main” java.lang.ClassCastException: java.lang.CloneNotSupportedException cannot be cast to org.arpit.java2blog.singleton.BillPughSingleton
at org.arpit.java2blog.singleton.CloningSingleonTest.main(CloningSingleonTest.java:7)

That’s all about Singleton Design pattern.

Was this post helpful?

Leave a Reply

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