What is the design pattern?
- In simple words, design patterns are best practices in the software development field.
- These design patterns are invented by well experienced Object-Oriented Software developers using their practice and experience.
Singleton design pattern
- This design pattern can be used to control object creation of the software development life cycle.
- If you use the Singleton design pattern, then you can have only one instance of that type.
How to create a Singleton object?
- Create private constructor (Then no one can instantiate this class, it means others can't create objects)
- Create the only one private static instance
- Create a public method to invoke this instance
Types of singleton implementations
There are several ways to implement a singleton class.
- Eager initialization
- Static block initialization
- Lazy initialization
- Thread-safe initialization
- Enum initialization
Eager initialization
- In this method, the instance is created at the time of class loading.
- The instance is created even the client is requesting or not.
public class Singleton{
private static final Singleton instance = new Singleton();
private Singleton() { }
public static Singleton getInstance() {
return instance;
}
}
Static block initialization
- This is very same as Eager initialization.
- The special thing is, we use the static block in getInstance() method to have exception handling.
public class Singleton{
private static Singleton instance;
private Singleton() { }
static{
try {
instance = new Singleton();
}catch (Exception e) {
System.out.println("Error : " + e);
}
}
public static Singleton getInstance(){
return instance;
}
}
Lazy initialization
- This is a good one in a single-threaded environment.
- But in a multithreaded environment, we have to use thread-safe initialization.
public class Singleton{
private static Singleton instance;
private Singleton() { }
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
The enum initialization
- This is the most efficient way to implement a singleton.
- Because it is very easy to write. Here is the way to implement it.
public enum EnumSingleton{
instance;
}
- You can get the instance by calling EnumSingleton.instance
Thread-safe initialization
- This is just very similar to Lazy initialization.
- But here synchronize the method that can be used to get the instance in a multi-threaded environment.
public class Singleton {
private volatile static Singleton instance;
private Singleton() { }
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
What is the double-checking on the Singleton design pattern?
- Just think, you are using the code like below.
synchronized (ThreadSafe.class){
if(instance ==null){
instance = new ThreadSafe();
}
}
- Here only one thread can acquire the lock of the object.
- If many threads want to get the instance, all threads need to wait until one thread releases the lock of the object.
- Since the synchronized block is using heavy CUP usage, it will consume more memory.
- To resolve this, we can double-check the instance as follows.
if(instance ==null){
synchronized (ThreadSafe.class){
if(instance ==null){
instance = new ThreadSafe();
}
}
}
- Now other threads will not reach the synchronized block. This will save CPU memory.
What is the use of Volatile?
- The volatile keyword can be used with variables.
- Volatile variables will not be cached in the cache memory.
- It will be saved only in the main memory.
- If one thread changed the value, all other threads can also see the changed value.
Which is the best one?
- The enum singleton implementation is the best way because it is very easy to implement and use.
- But this is available since Java 5.
When to use the Singleton design pattern?
- To manage shared resources(Database connections, file manager)
- Logging
- Catching
Singleton in JDK
There are many singleton classes that can be found in JDK. I listed three of them.
- In java.lang.Runtime which provides getRuntime() method.
- In java.awt.Toolkit which provides getDefaultToolkit() method.
- In java.awt.Desktop which provides getDesktop() method.
Top comments (0)