Singleton Design Pattern in Java

Java Singleton: 

a class that has only one instance and provides a global point of access to it

Advantage and usage of Singleton design pattern

  • Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine.
  • The singleton class must provide a global access point to get the instance of the class.
  • Singleton pattern is used for logging, drivers objects, caching and thread pool.
  • Singleton design pattern is also used in other design patterns like Abstract FactoryBuilderPrototypeFacade etc.
  • Singleton design pattern is used in core java classes also, for example java.lang.Runtimejava.awt.Desktop.

How to create Singleton design pattern?

Java Singleton Pattern

To implement Singleton pattern, we have different approaches but all of them have following common concepts.
  • Private constructor to restrict instantiation of the class from other classes.
  • Private static variable of the same class that is the only instance of the class.
  • Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
Eager initialization

package tutorials.interviewbubble.creationaldesignpattern;

public class EagerInitialization {
     // Private static variable of the same class that is the only instance of the class.
     private static EagerInitialization eagerInitSingleton = new EagerInitialization();
     
     //Private constructor to restrict instantiation of the class from other classes.
     private EagerInitialization(){
     
     }
//Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    public static EagerInitialization eagerInitSingletonOgject() {
             return eagerInitSingleton;
    }
    // Note: The static variable gets memory only once in class area at the time of class loading. That means when class get loaded one instance get created in Class Area 
    //even if no one has called its eagerInitSingletonOgject function till now. this happens because eagerInitSingleton object is static. it will get memory at the time of class loading.

}


package tutorials.interviewbubble.creationaldesignpattern;

public class SingletonPattern {

public static void main(String[] args) {
// EagerInitialization Singleton
EagerInitialization singaltonObject = EagerInitialization.eagerInitSingletonOgject();
System.out.println("Object Created Successfully Object is: "+singaltonObject);
}

}




Static Block initialization
package tutorials.interviewbubble.creationaldesignpattern;

public class StaticBlockInitialization {
// Private static variable of the same class that is the only instance of the class.
    private static StaticBlockInitialization staticInitSingleton;
    
    //static block initialization for exception handling
    static {
       try {
       staticInitSingleton = new StaticBlockInitialization();
       }catch(Exception e) {
       throw new RuntimeException("Error in Creating Singleton Object");
       }
    }
    
    //Private constructor to restrict instantiation of the class from other classes.
    private StaticBlockInitialization(){}
    
    //Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    public static StaticBlockInitialization getInstance() {
        return staticInitSingleton;
}
}


package tutorials.interviewbubble.creationaldesignpattern;

public class SingletonPattern {
// Static Block initialization Singleton
StaticBlockInitialization staticsingaltonObject = StaticBlockInitialization.getInstance();
System.out.println("Object Created Successfully Object is: "+staticsingaltonObject);

}



Lazy Initialization
package tutorials.interviewbubble.creationaldesignpattern;

public class LazyInitialization {
          // Private static variable of the same class that is the only instance of the class.
    private static LazyInitialization lazyInitialization;
     
    //Private constructor to restrict instantiation of the class from other classes.
    private LazyInitialization() {}
     
//Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    public static LazyInitialization lazyInitSingletonOgject() {
                  if(lazyInitialization == null)
                      return new LazyInitialization();   // new Object is Created only when no object is created till yet.
                  return lazyInitialization;
    }
}



package tutorials.interviewbubble.creationaldesignpattern;

public class SingletonPattern {

public static void main(String[] args) {

// Lazy initialization
LazyInitialization lazysingaltonObject = LazyInitialization.lazyInitSingletonOgject() ;
System.out.println("Object Created Successfully Object is: "+lazysingaltonObject);
}

}



Thread Safe Singleton

package tutorials.interviewbubble.creationaldesignpattern;

public class ThreadSafeSingleton {
// Private static variable of the same class that is the only instance of the class.
    private static ThreadSafeSingleton threadSafeSingleton;
    
    //Private constructor to restrict instantiation of the class from other classes.
    private ThreadSafeSingleton() {}
    
//Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    // To create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time
    public static synchronized ThreadSafeSingleton getInstance() { 
                  if(threadSafeSingleton == null)
                     return new ThreadSafeSingleton();   // new Object is Created only when no object is created till yet.
                  return threadSafeSingleton;
    }
}

A performance enhancement

In search of a performance enhancement, you might choose to rewrite the getInstance() method like this:

    public static ThreadSafeSingleton getInstance() { 
                  if(threadSafeSingleton == null) {
                  synchronized(ThreadSafeSingleton.class) {
                  threadSafeSingleton =  new ThreadSafeSingleton();   // new Object is Created only when no object is created till yet.
                  }
                }
                  return threadSafeSingleton;
    }

Instead of synchronizing the entire method, the preceding code fragment only synchronizes the critical code. However, the preceding code fragment is not thread-safe. Consider the following scenario: Thread 1 enters the synchronized block, and, before it can assign the singleton member variable, the thread is preempted. Subsequently, another thread can enter the if block. The second thread will wait for the first thread to finish, but we will still wind up with two distinct singleton instances. Is there a way to fix this problem? Read on.

Double-checked locking

 public static ThreadSafeSingleton getInstance() {
        if (threadSafeSingleton == null) {
            synchronized(ThreadSafeSingleton.class) {
                if (threadSafeSingleton == null) {
                    threadSafeSingleton = new ThreadSafeSingleton(); // new Object is Created only when no object is created till yet.
                }
            }
        }
        return threadSafeSingleton;
    }





package tutorials.interviewbubble.creationaldesignpattern;

public class ThreadSafeSingleton {
    // Private static variable of the same class that is the only instance of the class.
    private static ThreadSafeSingleton threadSafeSingleton;

    //Private constructor to restrict instantiation of the class from other classes.
    private ThreadSafeSingleton() {}

    //Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    // To create a thread-safe singleton class is to make the global access method synchronized so that only one thread can execute this method at a time
    public static ThreadSafeSingleton getInstance() {
        if (threadSafeSingleton == null) {
            synchronized(ThreadSafeSingleton.class) {
                if (threadSafeSingleton == null) {
                    threadSafeSingleton = new ThreadSafeSingleton(); // new Object is Created only when no object is created till yet.
                }
            }
        }
        return threadSafeSingleton;
    }
}


Unfortunately, double-checked locking is not guaranteed to work because the compiler is free to assign a value to the threadSafeSingleton member variable before the singleton's constructor is called. If that happens, Thread 1 can be preempted after the singleton reference has been assigned, but before the singleton is initialized, so Thread 2 can return a reference to an uninitialized singleton instance.
Since double-checked locking is not guaranteed to work, you must synchronize the entire getInstance() method. However, another alternative is simple, fast, and thread-safe.
Pros:
  1. Lazy initialization is possible.
  2. It is also thread safe.
  3. Performance reduced because of synchronized keyword is overcome.
Cons:
  1. First time, it can affect performance.

Bill Pugh Singleton

Prior to Java5, memory model had a lot of issues and above methods caused failure in certain scenarios in multithreaded environment. So, Bill Pugh suggested a concept of inner static classes to use for singleton.

Bill Pugh was main force behind the java memory model changes. His principle “Initialization-on-demand holder idiom” also uses the static block idea, but in a different way.

package tutorials.interviewbubble.creationaldesignpattern;

public class BillPughSingleton {

    // Private nest static class to provide instance of outer class.
    private static class LazyHolder {

        // Private static variable of the nested class that is the only instance of the outer class.
        private static final BillPughSingleton billPughSingleton = new BillPughSingleton();
    }

    //Private constructor to restrict instantiation of the class from other classes.
    private BillPughSingleton() {

    }

    //Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
    public static BillPughSingleton getInstance() {
        return LazyHolder.billPughSingleton;
    }

}

As you can see, until we need an instance, the LazyHolder class will not be initialized until required and you can still use other static members of BillPughSingleton class. This is the solution, I will recommend to use. I have used it for my all projects.



Comments