Singleton Design Pattern Part One
According to wiki
In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one “single” instance.
If we put it into simple word, we use singleton design pattern when we explicitly want to have only one instance of a given class. It is in the group of creational design pattern as we are dealing with the creation of object.
Real Life Use cases :
The most popular Spring Framework uses the singleton design pattern extensively. And singleton is the default bean scope in spring container, which tells the container to create and manage only one instance of bean class, per container.
java.lang.Runtime Every java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. the current runtime can be obtained from the getRuntime method.
Implementing the Singleton Design Pattern :
There are several ways of doing this in Java. I will demonstrate some of them.
- Declare a private constructor which will prevent other users from instantiating the class.
- Create the instance of the class during class loading via static field or block or a static method can be provided which will deal with the logic that if instance exist it will return that otherwise creates a new.
One caveat of Singleton design pattern is, it is tricky to write in concurrent environment.
1. Eagerly Initialized Singleton :
Well, this is the most single approach among all.
public class EagerlyInitializedSingleton {
/** private constructor to prevent others from instantiating this class */
private EagerlyInitializedSingleton(){}
/** creates an instance of the class at the time of class loading */
private static final EagerlyInitializedSingleton instance=new EagerlyInitializedSingleton();
/** this method provides the access of singleton instance */
public static EagerlyInitializedSingleton getInstance() {
return instance;
}
}
Well it's simple but have some disadvantages as well. If we look above code we can see that an instance is created weather it has any user or not. It can have performance implications if it allocates a large amount of system resources and remain unused.
2. Eagerly initialized Static Block Singleton :
We can create the instance of class in static block. This works because the static block is executed only once at the time of class loading.And we can see this trick used in many popular frameworks. The advantage of this approach is we can add custom logic before instantiating the object.
public class EagerStaticBlockSingleton{
private static final EagerStaticBlockSingleton instance;
/** Preventing others to instantiate this class */
private EagerStaticBlockSingleton() {}
/** Creates one-and-only instance in a static block */
static {
try {
//some logic
instance = new EagerStaticBlockSingleton();
} catch (Exception ex) {
throw ex;
}
}
/** Provide a public method to get the instance that we created */
public static EagerStaticBlockSingleton getInstance() {
return instance;
}
}
Just like previous example it creates the instance, weather three is a user or not.
3. Lazy Initialized Singleton (Not Thread Safe) :
public class Singleton {
private static Singleton instance;
/** private constructor prevent others from instantiating */
private Singleton(){}
/** lazy implementation of singleton */
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
Problem with this pattern ?
- Not thread safe.
The Synchronized Lazy Loaded Singleton Pattern
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (instance==null){
instance=new Singleton();
}
return instance;
}
}
The change in code is the synchronized in the getInstance() method. This will prevent the race condition in multi-threaded environment.
And how?
For example, suppose two threads entered in the getInstance() method and simultaneously. And both of them found instance==null and for that reason both of them creates a new instance of Singleton class. And that is not what we want. The synchronized keywords makes sure that only one thread can execute the getInstance() method.
By using synchronized keywords we can make it thread safe but it introduce some disadvantages as well.
- Since the read is synchronized, it can not be made in parallel.
- Once instance has been initialized, we want to be able to allow it's reading in parallel.
In next post I will provide the options to handle this problem.