Singleton Pattern

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

  1. package com.kb.singleton;
  2.  
  3. public class EagerSingletonClass {
  4.     private static volatile EagerSingletonClass singletonInstance = new EagerSingletonClass();
  5.    
  6.     //making constructor as private to prevent access to outsiders
  7.     private EagerSingletonClass() {
  8.        
  9.     }
  10.    
  11.     public static EagerSingletonClass getInstance(){
  12.         return singletonInstance;
  13.     }
  14.  
  15. }
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

  1. package com.kb.singleton;
  2.  
  3. import static org.junit.Assert.*;
  4.  
  5. import org.junit.Test;
  6.  
  7. public class EagerSingletonClassTest {
  8.  
  9.     @Test
  10.     public void testSingleton() {
  11.        
  12.         EagerSingletonClass instance1 = EagerSingletonClass.getInstance();
  13.         EagerSingletonClass instance2 = EagerSingletonClass.getInstance();
  14.         System.out.println("checking singleton objects equality");
  15.         assertEquals(true, instance1==instance2);
  16.        
  17.     }
  18.  
  19. }
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

  1. package com.kb.singleton;
  2.  
  3. public class LazySingleton {
  4.     private static volatile LazySingleton singletonInstance = null;
  5.    
  6.     //making constructor as private to prevent access to outsiders
  7.     private LazySingleton() {
  8.        
  9.     }
  10.    
  11.     public static LazySingleton getInstance(){
  12.         if(singletonInstance==null){
  13.             synchronized (LazySingleton.class) {
  14.                 singletonInstance = new LazySingleton();
  15.             }
  16.         }
  17.         return singletonInstance;
  18.     }
  19.  
  20.  
  21.  
  22. }
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

  1. package com.kb.singleton;
  2.  
  3. public class LazySingletonDoubleLockCheck {
  4.  
  5.     private static volatile LazySingletonDoubleLockCheck singletonInstance = null;
  6.    
  7.     //making constructor as private to prevent access to outsiders
  8.     private LazySingletonDoubleLockCheck() {
  9.        
  10.     }
  11.    
  12.     public static LazySingletonDoubleLockCheck getInstance(){
  13.         if(singletonInstance==null){
  14.             synchronized (LazySingleton.class) {
  15.                 if(singletonInstance ==null){
  16.                 singletonInstance = new LazySingletonDoubleLockCheck();
  17.                 }
  18.             }
  19.         }
  20.         return singletonInstance;
  21.     }
  22. }
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

  1. package com.kb.singleton;
  2.  
  3. import static org.junit.Assert.*;
  4.  
  5. import org.junit.Test;
  6.  
  7. public class LazySingletonDoubleLockCheckTest {
  8.  
  9.     @Test
  10.     public void testSingleton() {
  11.        
  12.         LazySingletonDoubleLockCheck instance1 = LazySingletonDoubleLockCheck.getInstance();
  13.         LazySingletonDoubleLockCheck instance2 = LazySingletonDoubleLockCheck.getInstance();
  14.         System.out.println("checking singleton objects equality");
  15.         assertEquals(true, instance1==instance2);
  16.         //fail("Not yet implemented");
  17.     }
  18.  
  19. }
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

  1. package com.kb.singleton;
  2.  
  3. public class SingletonUsingInnerClass {
  4.    
  5.     private SingletonUsingInnerClass() {
  6.        
  7.     }
  8.    
  9.     private static class LazySingleton{
  10.         private static final SingletonUsingInnerClass  SINGLETONINSTANCE = new SingletonUsingInnerClass();
  11.     }
  12.    
  13.     public static SingletonUsingInnerClass getInstance(){
  14.         return LazySingleton.SINGLETONINSTANCE;
  15.     }
  16.    
  17.  
  18. }
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

  1. package com.kb.singleton;
  2.  
  3. import static org.junit.Assert.*;
  4.  
  5. import org.junit.Test;
  6.  
  7. public class SingletonUsingInnerClassTest {
  8.  
  9.     @Test
  10.     public void testSingleton() {
  11.        
  12.         SingletonUsingInnerClass instance1 = SingletonUsingInnerClass.getInstance();
  13.         SingletonUsingInnerClass instance2 = SingletonUsingInnerClass.getInstance();
  14.         System.out.println("checking singleton objects equality");
  15.         assertEquals(true, instance1==instance2);
  16.     }
  17.  
  18. }
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

  1. package com.kb.singleton;
  2.  
  3. import java.io.Serializable;
  4.  
  5. public class SingletonSerializeAndDesrialize implements Serializable {
  6.    
  7.     private int x=100;
  8.    
  9.     private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize();
  10.  
  11.     private SingletonSerializeAndDesrialize() {
  12.  
  13.     }
  14.  
  15.     public static SingletonSerializeAndDesrialize getInstance() {
  16.         return singletonInstance;
  17.     }
  18.  
  19.     public int getX() {
  20.         return x;
  21.     }
  22.  
  23.     public void setX(int x) {
  24.         this.x = x;
  25.     }
  26.  
  27. }
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

  1. package com.kb.singleton;
  2.  
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.ObjectInput;
  7. import java.io.ObjectInputStream;
  8. import java.io.ObjectOutput;
  9. import java.io.ObjectOutputStream;
  10.  
  11. public class SerializeAndDeserializeTest {
  12.  
  13.     static SingletonSerializeAndDesrialize instanceOne = SingletonSerializeAndDesrialize.getInstance();
  14.  
  15.     public static void main(String[] args) {
  16.         try {
  17.             // Serialize to a file
  18.            
  19.             ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
  20.                     "filename.ser"));
  21.             out.writeObject(instanceOne);
  22.             out.close();
  23.  
  24.             instanceOne.setX(200);
  25.  
  26.             // Serialize to a file
  27.             ObjectInput in = new ObjectInputStream(new FileInputStream(
  28.                     "filename.ser"));
  29.             SingletonSerializeAndDesrialize instanceTwo = (SingletonSerializeAndDesrialize) in.readObject();
  30.             in.close();
  31.  
  32.             System.out.println(instanceOne.getX());
  33.             System.out.println(instanceTwo.getX());
  34.  
  35.         } catch (IOException e) {
  36.             e.printStackTrace();
  37.         } catch (ClassNotFoundException e) {
  38.             e.printStackTrace();
  39.         }
  40.     }}
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

  1. Access_modifier  Object readResolve() throws ObjectStreamException{
  2. }
Access_modifier  Object readResolve() throws ObjectStreamException{
}


Example

  1. Public Object readResolve() throws ObjectStreamException{
  2. return modifiedInstance;
  3. }
Public Object readResolve() throws ObjectStreamException{
return modifiedInstance;
}


Apply this to above singleton class, then complete singleton class is as below

Create SingletonSerializeAndDesrialize.java

  1. package com.kb.singleton;
  2.  
  3. import java.io.ObjectStreamException;
  4. import java.io.Serializable;
  5.  
  6. public class SingletonSerializeAndDesrialize implements Serializable {
  7.    
  8.     private int x=100;
  9.    
  10.     private static volatile SingletonSerializeAndDesrialize singletonInstance = new SingletonSerializeAndDesrialize();
  11.  
  12.     private SingletonSerializeAndDesrialize() {
  13.      System.out.println("inside constructor");
  14.     }
  15.  
  16.     public static SingletonSerializeAndDesrialize getInstance() {
  17.         return singletonInstance;
  18.     }
  19.  
  20.     public int getX() {
  21.         return x;
  22.     }
  23.  
  24.     public void setX(int x) {
  25.         this.x = x;
  26.     }
  27.    
  28.     public Object readResolve() throws ObjectStreamException{
  29.         return singletonInstance;
  30.         }
  31.  
  32.  
  33. }
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 :

  1.  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

  1. package com.kb.singleton;
  2.  
  3. import java.io.Serializable;
  4.  
  5. public class FinalSingleton implements Serializable{
  6.      private static final long serialVersionUID = 1L;
  7.    
  8.     private FinalSingleton() {
  9.        
  10.     }
  11.    
  12.     private static class LazyLoadFinalSingleton{
  13.         private static final FinalSingleton  SINGLETONINSTANCE = new FinalSingleton();
  14.     }
  15.    
  16.     public static FinalSingleton getInstance(){
  17.         return LazyLoadFinalSingleton.SINGLETONINSTANCE;
  18.     }
  19.    
  20.     private Object readResolve() {
  21.         return getInstance();
  22.     }
  23. }
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();
    }
}

About the Author

Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on