When Singleton should be used?
Singleton should be used incase creation of Object is costly or heavy I.E. DBConnection. It should not be used if the Object is mutable.
- Eager initialization
- Lazy initialization
- Static block initialization
- Using Synchronized method
- Using Synchronized block
- Double Checked Locking
- Enum Singleton
- Initialization on demand holder idiom
Eager initialization
An instance of Singleton Class is created at the time of class loading
EagerInitialized.java
package com.mugil.singleton; public class EagerInitialized { private static final EagerInitialized instance = new EagerInitialized(); //Private Constructor private EagerInitialized() { } public static EagerInitialized getInstance() { return instance; } }
Lazy Initialization
With lazy initialization you crate instance only when its needed and not when the class is loaded
LazyInitialized.java
package com.mugil.singleton; public class LazyInitialized { public static LazyInitialized instance = null; private LazyInitialized() { } public static LazyInitialized getInstance(){ if(instance == null){ instance = new LazyInitialized(); } return instance; } }
Static Block Initialization
Static block initialization is similar to eager initialization, except that an instance of class is created in the static block that provides an option for exception handling.
StaticBlockInitialized.java
package com.mugil.singleton; public class StaticBlockInitialized { private static StaticBlockInitialized instance; private StaticBlockInitialized() { } // Static block initialization for exception handling static { try { instance = new StaticBlockInitialized(); } catch (Exception e) { throw new RuntimeException("Exception occurred in creating singleton instance"); } } public static StaticBlockInitialized getInstance() { return instance; } }
Using Synchronized Method
The easier way to create a thread-safe singleton class is to make the access method synchronized, so that only one thread can execute this method at a time.
ThreadSafeSing.java
package com.mugil.singleton; public class ThreadSafeSing { private static ThreadSafeSinginstance; private ThreadSafeSing(){} public static synchronized ThreadSafeSing getInstance(){ if(instance == null){ instance = new ThreadSafeSing(); } return instance; } }
Using Synchronized Block
The easier way to create a thread-safe singleton class is to make the access method synchronized, so that only one thread can execute this method at a time.
ThreadSafeSing.java
package com.mugil.singleton; public class ThreadSafeSing { private static ThreadSafeSinginstance; private ThreadSafeSing(){} public static ThreadSafeSing getInstance(){ Synchronized(ThreadSafeSing.class){ if(instance == null){ instance = new ThreadSafeSing(); } } return instance; } }
Double Checked Locking Singleton
Above Implementation of Singleton provides thread safety buy has a hit over performance.Refer the link for the same Link
In the Below method of Implementing Singleton, Synchronized Block is used rather than Synchronized Method.
DCCSingleton.java
package com.mugil.singleton; public class DCCSingleton{ private static DCCSingletoninstance; private DCCSingleton(){} public static DCCSingleton getInstanceUsingDoubleLocking() { if(instance == null){ synchronized (DCCSingleton.class) { if(instance == null){ instance = new DCCSingleton(); } } } return instance; } }
Refer the Link for how Double Checked Locking works
ENUM Singleton
enum fields are compile time constants, but they are instances of their enum type. And, they’re constructed when the enum type is referenced for the first time.
ENUMSingleton.java
Simple Singleton using enum for DBConnection
enum Singleton { INSTANCE; // instance vars, constructor private final Connection connection; private Singleton() { //Initialize the connection connection = DB.getConnection(); } // Static getter public static Singleton getInstance() { return INSTANCE; } public Connection getConnection() { return connection; }
The Connection can be created using the Below Code
Connection Conn = Singleton.getInstance().getConnection();
Initialization on demand holder idiom
How it works?
- The Below implementation is a lazy loading and thread safe method of creating Singleton
- On calling the getInstance() method the lazySingletonClass would be initialized which in turn makes the INSTANCE to be initialized.
- Class initialization is inherently thread-safe and if you can have an object initialized on class initialization the object creation too are thread-safe.
- Singleton instance variable will never be created and or initialized until getInstance() is invoked. And again since class initialization is thread-safe the instance variable of IntiailizationOnDemandClassholder will be loaded safely, once and is visible to all threads.
public class Singleton { private Singleton(){} public static class lazySingletonClass{ private static final Singleton INSTANCE = new Singleton(); } public Singleton getInstance(){ return lazySingletonClass.INSTANCE; } }
When Object is Created | Thread Safe | Performance | Comments | |
---|---|---|---|---|
Eager Initialization | Object Gets Created once the Class is Loaded | Yes | Bad | Object is created everytime when the class is accessed |
Lazy Initialization | Object is Created once required | No | In lazy initialization you give a public API to get the instance. In multi-threaded environment it poses challenges to avoid unnecessary object creation | |
Static Block Initialization | Object is Created once Static Block is loaded | Yes | Bad | Not a good idea to load resources from static block as it causes performance hit during app startup |
Synchronized Method | Object is Created once getInstance is called | Yes | Bad | Thread safety is guaranteed.Slow performance because of whole method locking is done |
Synchronized Block | Object is Created once getInstance is called | No | Two singleton instances may be created when context switching happens after checking instance is null | |
Double Checked Locking | Object is Created once getInstance is called | Yes | Good | Instance check is done twice |
Enum Implementation | Object Created using enum is referenced | Yes | Good | |
Initialization on demand holder idiom | Object Created when static class is initiazlied by calling getInstance method | Yes | Good | Class initialization is inherently thread-safe and if you can have an object initialized on class initialization the object creation too are thread-safe |
Note
Dont be confused between Class Loading and Initialization. In the Initialization on demand holder method of singleton you can easily get confused as the static inner class wont be loaded when the outer class loads. The implementation relies on the fact that during initialization phase of execution within the Java Virtual Machine (JVM) as specified by the Java Language Specification (JLS) When the class Singleton is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition lazySingletonClasswithin it is not initialized until the JVM determines that lazySingletonClassmust be executed. The static class lazySingletonClassis only executed when the static method getInstance is invoked on the class
The static class lazySingletonClass is only executed when the static method getInstance is invoked on the class Singleton , and the first time this happens the JVM will load and initialize the lazySingletonClass class. The initialization of the lazySingletonClassclass results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be sequential, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization