Tuesday, October 20, 2015

[Singleton]

6. Singleton



Method1 - Early initialization: we create the object when the class is getting loaded into the JVM.
Method1 - Early initialization

public class JavaHungrySingleton
{

     private static JavaHungrySingleton uniqueInstance  = new JavahungrySingleton();
    
 private JavaHungrySingleton(){}

     // cannot be accessed by object
     public static JavaHungrySingleton getInstance()
     {
           return uniqueInstance;
     }
}



Method2 - Lazy initialization: Last moment to have an object. We create the object of the class only when it is about to use in the program code. deferred initialization
Advantage:
1. faster startup times, at the cost of delay caused by initialization the first time the instance is accessed
2. If never accessed, then never initialized, save initialization time and resources it would otherwise require if it were initialized by the classloader <== Method 1.
3. allow selection of the class of the singleton object to be deferred until run time rather than being specified at compile time.
Disadvantage: 
1. in a resource-limited environment, deferred initialization could fail due to inadequate resources.
2. increase the complecity of the singleton class, especially in a multi-threaded system.
3. If getInstance is called frequently, busy waiting due to synchronized ==> Method 3
Method2-   Lazy initialization + Synchronized(for thread-safe)

public class JavaHungrySingleton
{
 
     private static JavaHungrySingleton uniqueInstance = null ;

     private JavaHungrySingleton(){}

     public static synchronized JavaHungrySignleton getInstance ()
     {
           if (uniqueInstance == null)
           {
                  uniqueInstance = new JavaHungrySignleton();
           }
           return uniqueInstance;
     }
}



Method3 - Inner Class initializationThread-safe + Avoid overhead of synchronization

Method3 - Inner Class initialization :
Advantage:
  1. Thread-safe: because calssloader is guaranteed to be serialized, so the inner class is laoded and initialized only once, no matter how many threads call getInstance simutaneously.
  2. Avoid overhead of synchronization, because serialization is provided by classloader - after the class has been loaded, the classloader is no longer involved, so there’s no residual overhead.
public class JavaHungrySingleton
{

    private static JavaHungrySingleton uniqueInstance  = null;
   
    private JavaHungrySingleton(){}

    // Inner class initializea instacne on laod, won;t be loaded
    // until referenced by getInstance()
    private static class JavaHungrySingletonHolder()
    {
                public static final JavaHungrySingleton uniqueInstance = new JavaHungrySingleton();
    }

    // cannot be accessed by object
    public static JavaHungrySingleton getInstance()
    {
          return JavaHungrySingletonHolder.uniqueInstance;
    }
}


Method 3 - double checked locking: first we check if the object is created, if not then we create one using synchronized block.
Advantage:
1. reduce the overhead of acquiring a lock
Method 3 - double checked locking : Volatile(write before any read, invalidate all the read and flush)  + Double checked lock + Synchonized

public class JavaHungrySingleton
{

     private static volatile JavaHungrySingleton uniqueInstance;

     private JavaHungrySingleton(){}

     public static JavaHungrySingleton getInstance()
     {
            if (uniqueInstance == null)
            {
                    synchronized(JavaHungrySingleton.class)
                    {
                          if (uniqueInstance == null)
                          {
                                   uniqueInstance = new JavaHungrySingleton();
                           }
                     }
            }
            return uniqueInstance;
      }
}

volatile establishes happens-before relation between reads and writes, and fixes the broken pattern
volatile is here because without it
by the time second thread passes instance == null, first thread might not construct new Singleton() yet: no one promises that assignment to instance happens-before creation of the object for any thread but the one actually creating the object.

reduce the overhead of acquiring a lock by first testing the locking criterion (the "lock hint") without actually acquiring the lock
Reference:http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking 


1.What only one instance of whole application
It is the most used design pattern in web applications.
Singleton in Java is a class with just one instance in whole data java application and provides a getInstance() method to access the singleton instance .
For example, java.lang.Runtime is a singleton class. Creating Singleton was tricky prior Java 4 but once java 5 introduced Enum its very easy.

2. How
write Java singleton using double checked locking. Remember to use volatile variable to make Singleton thread-safe.
-create a static variable
private stati JavaHungrySingleton uniqueInstance;
-declare the constructor private
private JavaHungrySingleton() {}
-getInstance()
-public static synchronized JavaHungrySingleton getInstance(){}
-if (uniqueInstance == null )
uniqueInstance = new JavaHungrySingleton();
return uniqueInstance;


Reference:

No comments:

Post a Comment