Everybody knows what's Singleton class and Singleton Pattern, but here we see different approaches with detailed examples and where we use this pattern in general scenario. If you know what is a Singleton, I want you to go through this article once as this give you a detailed overview of singleton class in Java.
Singleton pattern
"The singleton pattern is one of the simplest design patterns: it involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance; in the same time it provides a global point of access to that instance. In this case the same instance can be used from everywhere, being impossible to invoke directly the constructor each time."
This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.
You use the Singleton pattern to satisfy four simultaneous requirements:
Implementation
In order to write a singleton class, you'll need to understand the following:
Let see how we are going to make a singleton class:
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
You can see from the above output that same instance is returned.
lazy initialization
The above code implements the concept of lazy initialization — meaning, you are creating the object of the singleton class, only when the getInstance() method is invoked. It also means that if the getInstance() method is not invoked, then the instance shall never be created
To implement the same LazySingleton in multi-threaded environment, you need to use the synchronized keyword.
This above code method uses double-checked locking, which should not be used prior to J2SE 5.0, as it is vulnerable to subtle bugs.
Well, this implementation is also not a foolproof solution for a multi-threaded application. It creates a problem due to erroneous out-of-order writes allowed by the Java memory model. Although the memory model problem was reportedly fixed in Java 5, we do not encourage you to use this solution.
The above solution can be made thread-safe in another way with the concept of eager instantiation
Eager initialization
If the program will always need an instance, or if the cost of creating the instance is not too large in terms of time/resources, the programmer can switch to eager initialization, which always creates an instance
Static block initialization
This approch allowing some pre-processing (e.g. for error-checking). In this sense, the traditional approach could be seen as a particular case of this one, as the class loader would do exactly the same processing
Demand holder idiom
"Double-checked locking" idiom led to changes in the Java memory model in Java 5 and to what is generally regarded as the standard method to implement Singletons in Java.
The technique known as the initialization on demand holder idiom, is as lazy as possible, and works in all known versions of Java.
It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines.
How it works
The implementation relies on the well-specified initialization phase of execution within the Java Virtual Machine (JVM).
When the class DemandHolderSingleton s 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 SingletonHolder within it is not initialized until the JVM determines that SingletonHolder must be executed. The static class SingletonHolder is only executed when the static method getInstance is invoked on the class DemandHolderSingleton and the first time this happens the JVM will load and initialize the LazyHolder class.
The initialization of the SingletonHolder class results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class DemandHolderSingleton .
When to use it
Use this pattern if the initialization of the class is expensive and it cannot be done safely at class-loading time and the initialization is concurrent. The crux of the pattern is the safe removal of the synchronization overhead associated with accessing a singleton instance
When not to use it
Avoid this idiom if the construction of INSTANCE can fail. If construction of INSTANCE fails, an invocation of Something.getInstance() will result in a java.lang.ExceptionInInitializerError error. Handling, or mishandling, of these types of construction initialization failures is a common criticism of this idiom and the singleton pattern in general.
The Enum way
In the second edition of his book Effective Java, Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any Java that supports enums. The use of an enum is very easy to implement and has no drawbacks regarding serializable objects.
Final example, that demonstrate Logger class:
Applicability & Examples
According to the definition the singleton pattern should be used when there must be exactly one instance of a class, and when it must be accessible to clients from a global access point. Here are some real situations where the singleton is used:
Related Post
Best Way to synchronized primitive datatypes in java
How Thread works in phases
How Threads exchanges data
Class Loader concept in detail
If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...
Singleton pattern
"The singleton pattern is one of the simplest design patterns: it involves only one class which is responsible to instantiate itself, to make sure it creates not more than one instance; in the same time it provides a global point of access to that instance. In this case the same instance can be used from everywhere, being impossible to invoke directly the constructor each time."
This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects.
You use the Singleton pattern to satisfy four simultaneous requirements:
- An application must have EXACTLY ONE instance of a particular class.
- The only instance must be accessible to client from a well-known access point.
- The sole instance should be extensible by subclassing.
- Clients must be able to use and extend the instance without modifying their own code.
Implementation
In order to write a singleton class, you'll need to understand the following:
- Implementation of a singleton pattern must satisfy the single instance and global access principles.
- It requires a mechanism to access the singleton class member without creating a class object and a mechanism to persist the value of class members among class objects
- The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object.
- To make sure that the object cannot be instantiated any other way, the constructor is made private
- The singleton pattern must be carefully constructed in multi-threaded applications.
Let see how we are going to make a singleton class:
- Creating a static variable of the instance of your singleton class will ensure that there are no two instances created at any given point.
- Exposing a method named getInstance() will return the instance of the class: either by creating it or returning the instance if it already exists.
- Singletons class constructor is declared as private so that the class could not be initialized from outside.
package Singleton; public class LazySingleton { private static LazySingleton instance; /* * Prevent instantiaton from other clasess */ private LazySingleton(){ } public static LazySingleton getInstance(){ if(instance==null){ instance = new LazySingleton(); } return instance; } }
package Singleton; public class LazySingletonDemo { public static void main(String[] javalatte) { for(int i=0;i<10;i++){ System.out.println(LazySingleton.getInstance()); } } }Sample Output
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
Singleton.LazySingleton@372f2b32
lazy initialization
The above code implements the concept of lazy initialization — meaning, you are creating the object of the singleton class, only when the getInstance() method is invoked. It also means that if the getInstance() method is not invoked, then the instance shall never be created
To implement the same LazySingleton in multi-threaded environment, you need to use the synchronized keyword.
package Singleton; public class LazySingletonSynchronized { private static LazySingletonSynchronized instance; /* * Prevent instantiaton from other clasess */ private LazySingletonSynchronized(){ } public static synchronized LazySingletonSynchronized getInstance(){ if(instance==null){ instance = new LazySingletonSynchronized(); } return instance; } }Using the synchronized keyword in this way will be extremely costly, because it's acted upon every time the getInstance() method is invoked. There is a different technique to avoid performance bottlenecks in applications, and this is to modify the code to synchronize only the assignment in the getInstance() method
package Singleton; public class LazySingletonSynchronized1 { private static LazySingletonSynchronized1 instance; /* * Prevent instantiaton from other clasess */ private LazySingletonSynchronized1(){ } public static LazySingletonSynchronized1 getInstance(){ if(instance==null){ synchronized(LazySingletonSynchronized1.class){ if(instance==null){ instance = new LazySingletonSynchronized1(); } } } return instance; } }
This above code method uses double-checked locking, which should not be used prior to J2SE 5.0, as it is vulnerable to subtle bugs.
Well, this implementation is also not a foolproof solution for a multi-threaded application. It creates a problem due to erroneous out-of-order writes allowed by the Java memory model. Although the memory model problem was reportedly fixed in Java 5, we do not encourage you to use this solution.
The above solution can be made thread-safe in another way with the concept of eager instantiation
Eager initialization
If the program will always need an instance, or if the cost of creating the instance is not too large in terms of time/resources, the programmer can switch to eager initialization, which always creates an instance
package Singleton; public class EagerSingleton { private static final EagerSingleton instance = new EagerSingleton(); private EagerSingleton(){ } public static EagerSingleton getInstance(){ return instance; } }This method has a number of advantages:
- The instance is not constructed until the class is used.
- There is no need to synchronize the getInstance() method, meaning all threads will see the same instance and no (expensive) locking is required.
- The final keyword means that the instance cannot be redefined, ensuring that one (and only one) instance ever exists.
Static block initialization
This approch allowing some pre-processing (e.g. for error-checking). In this sense, the traditional approach could be seen as a particular case of this one, as the class loader would do exactly the same processing
package Singleton; public class StaticSingleton { private static final StaticSingleton instance; static{ try{ instance = new StaticSingleton(); }catch(Exception ex){ throw new RuntimeException("oh, an error occurred!", ex); } } private StaticSingleton(){ } public static StaticSingleton getInstance(){ return instance; } }
Demand holder idiom
"Double-checked locking" idiom led to changes in the Java memory model in Java 5 and to what is generally regarded as the standard method to implement Singletons in Java.
The technique known as the initialization on demand holder idiom, is as lazy as possible, and works in all known versions of Java.
It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines.
package Singleton; public class DemandHolderSingleton { private DemandHolderSingleton(){ } /* * SingletonHolder is loaded on the first execution of Singleton.getInstance() * or the first access to SingletonHolder.INSTANCE, not before. */ public static class SingletonHolder{ public static final DemandHolderSingleton instance = new DemandHolderSingleton(); } public static DemandHolderSingleton getInstance(){ return SingletonHolder.instance; } }The nested class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).
How it works
The implementation relies on the well-specified initialization phase of execution within the Java Virtual Machine (JVM).
When the class DemandHolderSingleton s 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 SingletonHolder within it is not initialized until the JVM determines that SingletonHolder must be executed. The static class SingletonHolder is only executed when the static method getInstance is invoked on the class DemandHolderSingleton and the first time this happens the JVM will load and initialize the LazyHolder class.
The initialization of the SingletonHolder class results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class DemandHolderSingleton .
When to use it
Use this pattern if the initialization of the class is expensive and it cannot be done safely at class-loading time and the initialization is concurrent. The crux of the pattern is the safe removal of the synchronization overhead associated with accessing a singleton instance
When not to use it
Avoid this idiom if the construction of INSTANCE can fail. If construction of INSTANCE fails, an invocation of Something.getInstance() will result in a java.lang.ExceptionInInitializerError error. Handling, or mishandling, of these types of construction initialization failures is a common criticism of this idiom and the singleton pattern in general.
The Enum way
In the second edition of his book Effective Java, Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any Java that supports enums. The use of an enum is very easy to implement and has no drawbacks regarding serializable objects.
public enum EnumSingleton { INSTANCE; } OR public enum EnumSingleton { INSTANCE; public static EnumSingleton getInstance(){ return INSTANCE; } }
Final example, that demonstrate Logger class:
package Singleton; public class Logger { private Logger(){ } public static class Holder{ public static final Logger instance = new Logger(); } public static Logger getIntance(){ return Holder.instance; } public void log(String s){ System.err.println(s); } }
package Singleton; public class LoggerDemo { public static void main(String[] args) { Logger logger = Logger.getIntance(); logger.log("Hello, I'm logger instance"); } }
Applicability & Examples
According to the definition the singleton pattern should be used when there must be exactly one instance of a class, and when it must be accessible to clients from a global access point. Here are some real situations where the singleton is used:
- Logger Classes
The Singleton pattern is used in the design of logger classes. This classes are usually implemented as a singletons, and provides a global logging access point in all the application components without being necessary to create an object each time a logging operations is performed. - Configuration Classes
The Singleton pattern is used to design the classes which provides the configuration settings for an application. By implementing configuration classes as Singleton not only that we provide a global access point, but we also keep the instance we use as a cache object. When the class is instantiated( or when a value is read ) the singleton will keep the values in its internal structure. If the values are read from the database or from files this avoids the reloading the values each time the configuration parameters are used. - Accesing resources in shared mode
It can be used in the design of an application that needs to work with the serial port. Let's say that there are many classes in the application, working in an multi-threading environment, which needs to operate actions on the serial port. In this case a singleton with synchronized methods could be used to be used to manage all the operations on the serial port. - Factories implemented as Singletons
Let's assume that we design an application with a factory to generate new objects(Acount, Customer, Site, Address objects) with their ids, in an multithreading environment. If the factory is instantiated twice in 2 different threads then is possible to have 2 overlapping ids for 2 different objects. If we implement the Factory as a singleton we avoid this problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a common practice.
Related Post
Best Way to synchronized primitive datatypes in java
How Thread works in phases
How Threads exchanges data
Class Loader concept in detail
If you know anyone who has started learning java, why not help them out! Just share this post with them. Thanks for studying today!...
I loved it!!!
ReplyDeleteSuperb clarity those who dont know about singleton now he can able to handle singleton in his/her applications easily Pradeep
ReplyDeleteI appreciate you like it :) . Why don't you share this post with your friends, colleagues to help them in understanding the basic of Singleton.
DeleteI think it is a good tutorial.
ReplyDeleteHow to implement singleton pattern in java and some advice tips you can find some more at this adress link
your example Demand holder idiom has mistake you have written static modifier with class which is not allowed.
ReplyDelete