Saturday 10 November 2012

Singleton Design Pattern in Java

Singleton Design pattern in java

Singleton design pattern ensures that at any time there can only be one instance of a class and provide a global point of access to it.
Classes implementing Thread Pools, database Connection pools, caches, loggers etc are generally made Singleton so as to prevent any class from accidently creating multiple instances of such resource consuming classes.

Singleton design Pattern implementation:-
  1. Declare a default private constructor.
  2. Declare a private static variable to hold single instance of class.
  3. Declare a public static function that returns the single instance of class.
  4. Do “lazy initialization” in the accessor function. 

 class Singleton {  
     // 1. Make all constructors private  
     private Singleton() {}  
     // 2.   Declare a private static variable to hold single instance of class  
     private static Singleton INSTANCE = null;  
     // 3.   Declare a public static function that returns the single instance of class     
     public static Singleton getInstance() {  
       // 4. Do "lazy initialization" in the accessor function.  
       if(INSTANCE == null) {  
          INSTANCE = new Singleton();  
       }  
       return INSTANCE;  
     }  
 }  
 public class SingletonTest  
 {  
    public static void main(String[] args)  
    {  
       System.out.println("Singleton Test!");  
       // always return the same instance  
       System.out.println("Singleton instance id :"+Singleton.getInstance());  
       System.out.println("Singleton instance id :"+Singleton.getInstance());  
       System.out.println("Singleton instance id :"+Singleton.getInstance());  
       // can't create instance of Singleton class  
       //Singleton instance2 = new Singleton(); // Compilation Error  
    }  
 }  
Dealing with Multithreading in Singleton design pattern
 public static Singleton getInstance() {  
    if(INSTANCE == null) { // 1  
       INSTANCE = new Singleton(); // 2  
    }  
    return INSTANCE; // 3  
 }  
The above code can lead to creation of multiple instances in a multithreaded environment. Let’s take a closer look at the getInstance() method.

If one thread enters getInstance() method and finds the INSTANCE to be null at step 1 and enters the IF block and before it can execute step 2 another thread enters the method and executes step 1 which will be true as the INSTANCE is still null,  then it might lead to a situation (Race condition) where both the threads executes step 2 and create two instances of the Singleton class.

 // Recreate threading issue during instantiation of Singleton class  
 class Singleton {  
          // 1. Make all constructors private  
          private Singleton() {}  
          // 2.   Declare a private static variable to hold single instance of class  
          private static Singleton INSTANCE = null;  
          // 3.   Declare a public static function that returns the single instance of class   
          public static Singleton getInstance() {  
             if(INSTANCE == null) {  
               try {  
                  // If there is delay in creation of object then the threads might create multiple instances  
                  Thread.sleep(10);  
                  INSTANCE = new Singleton();  
               }  
               catch (InterruptedException ie) {  
                   ie.printStackTrace();  
               }         
              }  
              return INSTANCE;  
           }  
 }  
 public class SingletonThreadingTest implements Runnable  
 {  
         public void run() {                        
           System.out.println("Singleton instance id :"+Singleton.getInstance());  
         }  
         public static void main(String[] args)  
         {  
                 System.out.println("Singleton Test!");  
                 SingletonThreadingTest sei1 = new SingletonThreadingTest();  
                 Thread thread1 = null;  
                 for(int i=0; i< 2;i++) {  
                         thread1 = new Thread(sei1);  
                         // might create mutliple instances of Singleton class  
                         thread1.start();  
                 }  
         }  
 }  

Eager instantiation in Singleton design pattern


We can prevent this issue by making the getInstance() method ‘synchronized’ but that will decrease the performance of your system as only single thread can access the getInstance method at a time. The other way could be to eagerly instantiate the INSTANCE variable.
Also if your application always creates and uses the singleton instance and overhead of creation of singleton instance is not a major point of concern then also we can create the instance of the class eagerly.

 // Eager instantiation of Singleton class  
 class Singleton {  
          // 1. Make all constructors private  
          private Singleton() {}  
          // 2.   Eagerly declare a private static variable to hold single instance of class  
          private static Singleton INSTANCE = new Singleton();  
          // 3.   Declare a public static function that returns the single instance of class   
          public static Singleton getInstance() {  
                 return INSTANCE;  
          }  
 }  
 public class SingletonEagerInstantiationTest  
 {  
         public static void main(String[] args)  
         {  
                 System.out.println("Singleton Test!");  
                 // always return the same instance  
                 System.out.println("Singleton instance id :"+Singleton.getInstance());  
                 System.out.println("Singleton instance id :"+Singleton.getInstance());  
                 System.out.println("Singleton instance id :"+Singleton.getInstance());  
                 // can't create instance of Singleton class  
                 //Singleton instance2 = new Singleton(); // Compilation Error  
         }  
 }  
Double checked locking method
Another way to prevent multithreading issue is to use ‘Double checked Locking method’ to reduce the use of synchronization in getInstance() method. In this method the synchronized block is placed inside the first NULL check condition so the synchronized block will be executed only initially when the initialization of instance is not done. Its called double checked as we check the nullability of INSTANCE twice. 
 // Double checked locking method  
 class Singleton {  
          // 1. Make all constructors private  
          private Singleton() {}  
          // 2.   volatile keyword ensures that multiple threads handle the INSTANCE variable  
          //     correctly when it is being initiaized.  
          private volatile static Singleton INSTANCE = null;  
          // 3.   method is not made synchronized  
          public static Singleton getInstance() {  
                  // check that INSTANCE is initialized and if not then enter  
                  // synchronized block  
                 if(INSTANCE == null) {  
                         synchronized(Singleton.class) {  
                                 // inside the block check again for initialization  
                                 if(INSTANCE == null) {  
                                         INSTANCE = new Singleton();  
                                 }  
                         }  
                 }  
                 return INSTANCE;  
          }  
 }  
 public class SingletonDoubleCheckedLockingTest implements Runnable  
 {  
         public void run() {                        
           System.out.println("Singleton instance id :"+Singleton.getInstance());  
         }  
         public static void main(String[] args)  
         {  
                 System.out.println("Singleton Test!");  
                 SingletonDoubleCheckedLockingTest sei1 = new SingletonDoubleCheckedLockingTest();  
                 Thread thread1 = null;  
                 for(int i=0; i< 2;i++) {  
                         thread1 = new Thread(sei1);  
                         // might create mutliple instances of Singleton class  
                         thread1.start();  
                 }  
         }  
 }  

You can read more about singleton design pattern from the below links:-
http://en.wikipedia.org/wiki/Singleton_pattern

No comments:

Post a Comment

/* */