Singleton Pattern
- 4th Sep 2014
- 12
- 48465
- different approches to achieve the singleton design pattern how many ways we can achieve singleton design pattern in java with an example singleton design pattern in java with an example singleton design pattern through eager initialization singleton design pattern through lazy initialization Singleton using Inner class in java with an example Singleton with serialization and de-serialization in java what is singleton design pattern in java with an example
Singleton Design Pattern is one of the simplest design pattern in Java.
If any one asks me which design pattern you are good at, then I would say Singleton.
But when they ask in depth concept of singleton then I get stumped.
Singleton design pattern is really that much difficult ?
Really not 🙂 , But it has many scenarios that we need to understand especially beginners.
Definition
There should be only one instance allowed for the class in all the situation and we should provide global point of access to that instance. Definition is as easy as 1,2,3 and A,B,C,D.
Let’s see how can we implement Singleton Class.
How can we ensure object should be only one all the time ?
Put object creation logic in only one place and don’t allow users to execute this logic every time they try to but allow only once.
How can we create object in Java ?
By using constructor , We should not allow users to access constructor and execute it every time they try to.
But we should do it one time to get one object at least.
How can we ensure constructor is accessible and executable only once ?
1) Prevent constructor access outside the class so that no outsiders can be able to create an instance.
How to prevent method access outside class ?
Simple make method and constructor as private.
2) Prevent constructor execution inside the class more than once.
How to make it -> This can be implement in many ways, lets see them with an example.
If the above Prevent constructor conditions are satisfied then we will have always one object for our class and that class is called as Singleton as it produces single object all the time we request.
In Different Ways we can create singleton object
Approach 1
Eager initialization (or) initialize before use
Create EagerSingletonClass.java
- package com.kb.singleton;
- public class EagerSingletonClass {
- private static volatile EagerSingletonClass singletonInstance = new EagerSingletonClass();
- //making constructor as private to prevent access to outsiders
- private EagerSingletonClass() {
- }
- public static EagerSingletonClass getInstance(){
- return singletonInstance;
- }
- }
package com.kb.singleton; public class EagerSingletonClass { private static volatile EagerSingletonClass singletonInstance = new EagerSingletonClass(); //making constructor as private to prevent access to outsiders private EagerSingletonClass() { } public static EagerSingletonClass getInstance(){ return singletonInstance; } }
The instance of EagerSingletonClass is created at the startup of the class.
Since it’s a static, it gets loaded and created during loading of the EagerSingletonClass.
Junit test class for the above class to test singleton.
Create EagerSingletonClassTest.java
- package com.kb.singleton;
- import static org.junit.Assert.*;
- import org.junit.Test;
- public class EagerSingletonClassTest {
- @Test
- public void testSingleton() {
- EagerSingletonClass instance1 = EagerSingletonClass.getInstance();
- EagerSingletonClass instance2 = EagerSingletonClass.getInstance();
- System.out.println("checking singleton objects equality");
- assertEquals(true, instance1==instance2);
- }
- }
package com.kb.singleton; import static org.junit.Assert.*; import org.junit.Test; public class EagerSingletonClassTest { @Test public void testSingleton() { EagerSingletonClass instance1 = EagerSingletonClass.getInstance(); EagerSingletonClass instance2 = EagerSingletonClass.getInstance(); System.out.println("checking singleton objects equality"); assertEquals(true, instance1==instance2); } }
Advantage :
This strategy creates the object during the loading of the class and hence its faster and safer from multithreading scenario.
Only thing we have to make instance as volatile for handling multi threading scenario.
Disadvantage :
This strategy creates the instance during class loading itself, Hence if we don’t use then it’s a waste of whole time and memory taken to create the instance.
So better to create an instance as and when we require it.
When to use above strategy ?
Whenever we are 100% sure that object is definitely used in our application.
(OR)
When the object is not heavy also its ok we can manage speed and memory.
Approach 2
Lazy initialization (or) initialize as and when we need, Instead of creating an object at the startup.
Create LazySingleton.java
- package com.kb.singleton;
- public class LazySingleton {
- private static volatile LazySingleton singletonInstance = null;
- //making constructor as private to prevent access to outsiders
- private LazySingleton() {
- }
- public static LazySingleton getInstance(){
- if(singletonInstance==null){
- synchronized (LazySingleton.class) {
- singletonInstance = new LazySingleton();
- }
- }
- return singletonInstance;
- }
- }
package com.kb.singleton; public class LazySingleton { private static volatile LazySingleton singletonInstance = null; //making constructor as private to prevent access to outsiders private LazySingleton() { } public static LazySingleton getInstance(){ if(singletonInstance==null){ synchronized (LazySingleton.class) { singletonInstance = new LazySingleton(); } } return singletonInstance; } }
In the above program, we have created an object only when there is a request through getInstance() method.
Here during the first invocation of getInstance(), the object ‘singletonInstance’ will be null and it executes the if condition block as it becomes true and creates an object.
Then subsequent calls to getInstance() method will return the same object , But if we look at the multithreading scenario problem comes when below context comes
2 threads t1 and t2 calls getInstance() method and thread t1 executes
if(singletonInstance == null) and finds singletonInstance as null so it enters the synchronized block to create an object.
But, before it executes the object creation logic if thread t2 executes if(singletonInstance == null) then it will also find singletonInstance as null so it will also try to enter synchronized block
But it will not have a lock as the first thread t1 already entered so thread t2 waits for the thread t1 to complete the execution of synchronized block
Hence, thread t1 executes and creates the object.
Now thread t2 also enters the synchronized block as it was waiting for the synchronized block and creates the object once again.
So two objects are created by 2 threads. So fails to achieve singleton.
Solution to the above problem is “Double Checked Locking”
It says re-check the instance variable again inside the synchronized block before we execute the logic of object creation inside synchronized block.
So in this way we can avoid the creation of object more than one by multiple threads, But how ? can you elaborate it ?
Thread t1 checks the condition if(singletonInstance == null) and it is true for first time so it enters synchronized block and there again it checks the condition if(singletonInstance == null) and this is also true so creates the object.
Now thread t2 enters the method getInstance() and assume it has executed if(singletonInstance == null)) condition before the thread t1 executes the object creation logic then t2 also waits to enter the synchronized block.
After thread t1 comes out of synchronized block thread t2 enters the same block but we have if condition again there
if(singletonInstance == null) but thread t1 already created an object it makes the condition to be false and stop the execution further and returns the same instance.
Let’s see how it can be done in code
Create LazySingletonDoubleLockCheck.java
- package com.kb.singleton;
- public class LazySingletonDoubleLockCheck {
- private static volatile LazySingletonDoubleLockCheck singletonInstance = null;
- //making constructor as private to prevent access to outsiders
- private LazySingletonDoubleLockCheck() {
- }
- public static LazySingletonDoubleLockCheck getInstance(){
- if(singletonInstance==null){
- synchronized (LazySingleton.class) {
- if(singletonInstance ==null){
- singletonInstance = new LazySingletonDoubleLockCheck();
- }
- }
- }
- return singletonInstance;
- }
- }
package com.kb.singleton; public class LazySingletonDoubleLockCheck { private static volatile LazySingletonDoubleLockCheck singletonInstance = null; //making constructor as private to prevent access to outsiders private LazySingletonDoubleLockCheck() { } public static LazySingletonDoubleLockCheck getInstance(){ if(singletonInstance==null){ synchronized (LazySingleton.class) { if(singletonInstance ==null){ singletonInstance = new LazySingletonDoubleLockCheck(); } } } return singletonInstance; } }
Let’s do the unit testing
Create LazySingletonDoubleLockCheckTest.java
- package com.kb.singleton;
- import static org.junit.Assert.*;
- import org.junit.Test;
- public class LazySingletonDoubleLockCheckTest {
- @Test
- public void testSingleton() {
- LazySingletonDoubleLockCheck instance1 = LazySingletonDoubleLockCheck.getInstance();
- LazySingletonDoubleLockCheck instance2 = LazySingletonDoubleLockCheck.getInstance();
- System.out.println("checking singleton objects equality");
- assertEquals(true, instance1==instance2);
- //fail("Not yet implemented");
- }
- }
package com.kb.singleton; import static org.junit.Assert.*; import org.junit.Test; public class LazySingletonDoubleLockCheckTest { @Test public void testSingleton() { LazySingletonDoubleLockCheck instance1 = LazySingletonDoubleLockCheck.getInstance(); LazySingletonDoubleLockCheck instance2 = LazySingletonDoubleLockCheck.getInstance(); System.out.println("checking singleton objects equality"); assertEquals(true, instance1==instance2); //fail("Not yet implemented"); } }
The above implementation is the best advisable solution for singleton pattern which is best suitable for all scenarios like single threaded, multithreaded.
Approach 3
Singleton using Inner class
Create SingletonUsingInnerClass.java
- package com.kb.singleton;
- public class SingletonUsingInnerClass {
- private SingletonUsingInnerClass() {
- }
- private static class LazySingleton{
- private static final SingletonUsingInnerClass SINGLETONINSTANCE = new SingletonUsingInnerClass();
- }
- public static SingletonUsingInnerClass getInstance(){
- return LazySingleton.SINGLETONINSTANCE;
- }
- }
package com.kb.singleton; public class SingletonUsingInnerClass { private SingletonUsingInnerClass() { } private static class LazySingleton{ private static final SingletonUsingInnerClass SINGLETONINSTANCE = new SingletonUsingInnerClass(); } public static SingletonUsingInnerClass getInstance(){ return LazySingleton.SINGLETONINSTANCE; } }
Unit test code
Create SingletonUsingInnerClassTest.java
- package com.kb.singleton;
- import static org.junit.Assert.*;
- import org.junit.Test;
- public class SingletonUsingInnerClassTest {
- @Test
- public void testSingleton() {
- SingletonUsingInnerClass instance1 = SingletonUsingInnerClass.getInstance();
- SingletonUsingInnerClass instance2 = SingletonUsingInnerClass.getInstance();
- System.out.println("checking singleton objects equality");
- assertEquals(true, instance1==instance2);
- }
- }
package com.kb.singleton; import static org.junit.Assert.*; import org.junit.Test; public class SingletonUsingInnerClassTest { @Test public void testSingleton() { SingletonUsingInnerClass instance1 = SingletonUsingInnerClass.getInstance(); SingletonUsingInnerClass instance2 = SingletonUsingInnerClass.getInstance(); System.out.println("checking singleton objects equality"); assertEquals(true, instance1==instance2); } }
The above approach of creating object using inner class is one of the best approach to create singleton object.
Here unless and until someone tries to access the static reference variable of LazySingleton static inner class, the object will not be created.
So this will also ensure the creation of object as and when it’s required and it’s very simple to implement yet safe from multi threading.
Approach 4
Singleton with serialization and de-serialization
Now assume our application is distributed and we serialize our singleton object and write it to file.
Later we read it by de-serializing the singleton object.
De-serializing the object always creates a new object with the state available inside the file.
If we do any state change after writing to a file and then try to de-serialize the object , we will get original object not new state object.
So we got 2 objects in this process.
Let’s try to understand this problem in programmatic way
Step 1 : Make the singleton class serializable to serialize and deserialize this class’s object.
Step 2 : Write the object to file(serialization)
Step 3 : Change the object state
Step 4 : De-serialize the object
Create SingletonSerializeAndDesrialize.java
- package com.kb.singleton;
- import java.io.Serializable;
- public class SingletonSerializeAndDesrialize implements Serializable {
- private int x=100;
- private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize();
- private SingletonSerializeAndDesrialize() {
- }
- public static SingletonSerializeAndDesrialize getInstance() {
- return singletonInstance;
- }
- public int getX() {
- return x;
- }
- public void setX(int x) {
- this.x = x;
- }
- }
package com.kb.singleton; import java.io.Serializable; public class SingletonSerializeAndDesrialize implements Serializable { private int x=100; private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize(); private SingletonSerializeAndDesrialize() { } public static SingletonSerializeAndDesrialize getInstance() { return singletonInstance; } public int getX() { return x; } public void setX(int x) { this.x = x; } }
Serialize our object then do some change in the state and then de serialize it.
Create SerializeAndDeserializeTest.java
- package com.kb.singleton;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.ObjectInput;
- import java.io.ObjectInputStream;
- import java.io.ObjectOutput;
- import java.io.ObjectOutputStream;
- public class SerializeAndDeserializeTest {
- static SingletonSerializeAndDesrialize instanceOne = SingletonSerializeAndDesrialize.getInstance();
- public static void main(String[] args) {
- try {
- // Serialize to a file
- ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
- "filename.ser"));
- out.writeObject(instanceOne);
- out.close();
- instanceOne.setX(200);
- // Serialize to a file
- ObjectInput in = new ObjectInputStream(new FileInputStream(
- "filename.ser"));
- SingletonSerializeAndDesrialize instanceTwo = (SingletonSerializeAndDesrialize) in.readObject();
- in.close();
- System.out.println(instanceOne.getX());
- System.out.println(instanceTwo.getX());
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }}
package com.kb.singleton; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; public class SerializeAndDeserializeTest { static SingletonSerializeAndDesrialize instanceOne = SingletonSerializeAndDesrialize.getInstance(); public static void main(String[] args) { try { // Serialize to a file ObjectOutput out = new ObjectOutputStream(new FileOutputStream( "filename.ser")); out.writeObject(instanceOne); out.close(); instanceOne.setX(200); // Serialize to a file ObjectInput in = new ObjectInputStream(new FileInputStream( "filename.ser")); SingletonSerializeAndDesrialize instanceTwo = (SingletonSerializeAndDesrialize) in.readObject(); in.close(); System.out.println(instanceOne.getX()); System.out.println(instanceTwo.getX()); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
It clearly says we have 2 distinct objects even though its singleton.
This is happening because de-serialization creates new instance with the state available in the file.
How to overcome this problem and how to prevent creating new instance during de-serialization ?
Solution is very simple – Implement below method in your singleton class
- Access_modifier Object readResolve() throws ObjectStreamException{
- }
Access_modifier Object readResolve() throws ObjectStreamException{ }
Example
- Public Object readResolve() throws ObjectStreamException{
- return modifiedInstance;
- }
Public Object readResolve() throws ObjectStreamException{ return modifiedInstance; }
Apply this to above singleton class, then complete singleton class is as below
Create SingletonSerializeAndDesrialize.java
- package com.kb.singleton;
- import java.io.ObjectStreamException;
- import java.io.Serializable;
- public class SingletonSerializeAndDesrialize implements Serializable {
- private int x=100;
- private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize();
- private SingletonSerializeAndDesrialize() {
- System.out.println("inside constructor");
- }
- public static SingletonSerializeAndDesrialize getInstance() {
- return singletonInstance;
- }
- public int getX() {
- return x;
- }
- public void setX(int x) {
- this.x = x;
- }
- public Object readResolve() throws ObjectStreamException{
- return singletonInstance;
- }
- }
package com.kb.singleton; import java.io.ObjectStreamException; import java.io.Serializable; public class SingletonSerializeAndDesrialize implements Serializable { private int x=100; private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize(); private SingletonSerializeAndDesrialize() { System.out.println("inside constructor"); } public static SingletonSerializeAndDesrialize getInstance() { return singletonInstance; } public int getX() { return x; } public void setX(int x) { this.x = x; } public Object readResolve() throws ObjectStreamException{ return singletonInstance; } }
Now run our above serialize and deserialize class to check the output for both the instances
This is because, during de-serialization it calls readResolve() method and there we are returning the existing instance which prevents creating new instance and ensures singleton object.
Serial version id
Whenever the class structure gets change after we serialize and before we de serialize it.
Then during de-serialization process , it finds an compatible class and hence throws an exception
java.io.InvalidClassException: SingletonClass; local class incompatible: stream classdesc serialVersionUID = 5026910492258526905, local class serialVersionUID = 3597984220566440782
So to avoid this exception we have to use serial version id to the serializable class always.
Syntax :
- private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
So finally by covering all the above scenarios, the best possible solution of singleton class is
Create FinalSingleton.java
- package com.kb.singleton;
- import java.io.Serializable;
- public class FinalSingleton implements Serializable{
- private static final long serialVersionUID = 1L;
- private FinalSingleton() {
- }
- private static class LazyLoadFinalSingleton{
- private static final FinalSingleton SINGLETONINSTANCE = new FinalSingleton();
- }
- public static FinalSingleton getInstance(){
- return LazyLoadFinalSingleton.SINGLETONINSTANCE;
- }
- private Object readResolve() {
- return getInstance();
- }
- }
package com.kb.singleton; import java.io.Serializable; public class FinalSingleton implements Serializable{ private static final long serialVersionUID = 1L; private FinalSingleton() { } private static class LazyLoadFinalSingleton{ private static final FinalSingleton SINGLETONINSTANCE = new FinalSingleton(); } public static FinalSingleton getInstance(){ return LazyLoadFinalSingleton.SINGLETONINSTANCE; } private Object readResolve() { return getInstance(); } }
Hi KB,
I have one question related to Singleton Design pattern for multi threading.
public static LazySingletonDoubleLockCheck getInstance(){
if(singletonInstance==null){
synchronized (LazySingleton.class) {
if(singletonInstance ==null){
singletonInstance = new LazySingletonDoubleLockCheck();
}
}
}
return singletonInstance;
}
}
Cann’t we make the whole method as synchronized (public static synchronized LazySingletonDoubleLockCheck getInstance()) ?.
please correct me if my understanding is wrong
Hi KB,
Change the commented line number 26 at SerializeAndDeserializeTest.java in Approach 4 that is // Serialize to a file to Deserialize to a file just to avoid confusion especially for the beginners.
Consider it as a minor suggestion.
Can you plse update some more design pattern that we use in project .
thanks
raghavendra
Sure Raghavendra, its in my plan.
Thanks !!
thanks sir,
Looking forward which some more example on DP
Hello
I really liked your blog.however in this post i would like to add something ,
you have mentioned there that
*How we create object in Java ?
Yes using constructor , and we should not allow users to access constructor and execute it every time they try to. *
I believe this statement is completely wrong. constructor is executed that does not mean object is created. object is create only using new operator and constructor is executed to initialize the instance variable.
Kindly correct it.. 🙂
thanks again.
Thanks PushP for bringing this into discussion!!
Let me try to make you understand the below line
we should not allow users to access constructor and execute it every time they try to.
If we are making someone to access constructor I mean execute constructor multiple times it just creates new object according to Java concept.
How ?
you know that constructors don’t have names right,so the only we to make the constructor execution is by creating an object using new.
I agree that constructor execution and object creation are different activities but my point here is when you allow someone to execute the constructor multiple times, it means you are calling constructors multiple times because there is no other way to execute the constructors.
Note:going through programmatically not through reflection and all.
your opinion
constructor is executed that does not mean object is created , object is created only using new operator and constructor is executed to initialize the instance variable
my understanding on your opinion
if I go by English i agree with this sentence , but going by Java concept i can not agree with this.
Because when constructor is executed it means that you have called it using new class_name(), it means one object gets created in Java.
I am not saying constructor execution and object creation are synonyms but what i am saying is they are mutually dependent.
So my point here is simple,
we should not allow users create object multiple times which is same as we should not allow users to execute the constructors multiple times.
preventing constructor execution is same as not allowing someone to create an object.
Happy to hear your inputs again and Thank you so much !!
Hi Mani,,,
I have added subscribe option on the right sidebar, you can subscribe there to receive the updates 🙂
Thank you once again…and welcome for your comments always.
Mail me when you write a new one 🙂
sure 🙂
Hi Mani, Its really very good notice…
I forgot to add clone and also i didn’t add one more approach using ENUM.
But Reflection you are right , i didnt notice this situation. but its good to cover that as well.
so i will edit this post sometime to include all the above scenarios.
Thanks a lot for reading , observing the things and suggesting.
Keep Suggesting the posts during your free time 🙂 Thank you once again…
Good one, KB 🙂
—
I can break your code using reflection though:
===
// Access constructor using reflection
Class clazz = FinalSingleton.class;
Constructor cons = clazz.getDeclaredConstructor();
cons.setAccessible(true);
FinalSingleton instanceThree = cons.newInstance();
instanceThree.setX(300);
System.out.println(“instanceThree.getX() :: “+instanceThree.getX());
===
the above creates a new instance.you can avoid that by changig your constructor
===
private FinalSingleton() {
//If-block needed to avoid creation of another object using reflection
/*if (LazyLoadFinalSingleton.SINGLETONINSTANCE != null) {
throw new IllegalStateException(“Inside FinalSingleton(): instance already created.”);
}*/
x = 100;
System.out.println(“Constructor Called. Instance created.”);
}
===
Also good to override clone method and throw clone not supported exception. You will never know where the loop hole is. 🙂