Singleton is a class which has only one instance in whole application and provides a getInstance() method to access the singleton instance.
There are many classes in JDK which is implemented using Singleton pattern like java.lang.Runtime which provides getRuntime() method to get access and is used to get free memory and total memory in Java.
Any class which you want it to make available to whole application and only one instance is viable can be made as a Singleton class.
One example of this is Runtime class as on whole java application only one runtime environment is possible and so making Runtime as singleton can be considered as right decision.
Another example is a utility class say for instance 'Popup' in 'GUI application' where you can show popup with a message. Here you can have one PopUp class on whole GUI application where you just need to get instance anytime and call 'show()' method with message.
There are a number of ways to implement Singleton class like using double checked locking or Singleton class with static final instance that can be initialized during class loading.
The former is called 'lazy loading' because Singleton instance is created only when client calls 'getInstance()' method while later is called 'early loading' because Singleton instance is created when class is loaded into memory.
There are many classes in Java Development Kit which is written using singleton pattern, some of which are as mentioned below:
Java.lang.Runtime with getRuntime() method
Java.awt.Toolkit with getDefaultToolkit()
Java.awt.Desktop with getDesktop()
Double checked locking' in singleton is a technique to prevent the creation of another instance of Singleton when a call is made to the 'getInstance()' method in multi-threading environment. In 'Double checked locking pattern' as shown in below example, singleton instance is checked two times before initialization.
public static Singleton getInstance()
{
if(_INSTANCE == null)
{
synchronized(Singleton.class)
{
// double checked locking -
// because second check of Singleton instance with lock
if(_INSTANCE == null)
{
_INSTANCE = new Singleton();
}
}
}
return _INSTANCE;
}
'Double checked locking' should only be used when you have requirement for 'lazy initialization' otherwise use 'Enum' to implement 'singleton' or 'simple static final variable'.
It is advised not to implement 'Cloneable' interface by creating 'clone()' method Singleton. One can do this using throw Exception from clone() method as “Cannot create clone of Singleton class”.
Since constructor of Singleton class is supposed to be private, it prevents creating instance of Singleton from outside but Reflection can access private fields and methods, which opens a threat of another instance. This can be avoided by throwing Exception from constructor as “Singleton already initialized”
You can prevent the creation of another instance of singleton during serialization using 'readResolve()' method, since during serialization 'readObject()' method is used to create instance and it returns new instance every time but by using 'readResolve()' method you can replace it with original Singleton instance.
Singleton Dependency Injection: every class that needs access to a singleton gets the object through its constructors or with a DI-container.
With more and more classes calling 'getInstance()' method the code gets more and more tightly coupled, monolithic, not testable and hard to change as well as hard to reuse because of non-configurable and hidden dependencies. Also, there would be no need for this clumsy double checked locking if you call 'getInstance()' method less often (i.e. once a while).
One can implement Singleton pattern in Java in four ways:
Singleton by synchronizing 'getInstance()' method.
Singleton with 'public static final' field initialized during class loading.
Singleton generated by 'static' nested class, also referred as 'Singleton' holder pattern.
From Java 5 onwards, Singleton class in Java can be written using Enum.
Thread safe Singleton usually refers to writing thread safe code which creates one and only one instance of Singleton if called by 'multiple' threads at the same time.
There are many ways to achieve this say for instance by using 'double checked locking' technique as shown above and by using 'Enum' or 'Singleton' initialized by class loader.