In this article, we will discuss how to write Java code to create Thread-safe Singleton class in a Multi-threaded environment
Before starting to write code for Singleton class, we should know all possible ways to create new Object and then find the way to suppress it
1. Ways to create & suppress Object :
Sr. No. | Creation | Suppress |
1. | new keyword | Provide private constructor which restricts to create new Object from outside of the class |
2. | Reflection API | Reflection API at runtime allows to create new Object therefore add additional check and throw Runtime Exception |
3. | De Serialization | De-serializing a file/network stored serialized Object creates new Object so override readResolve() method and return same Singleton instance |
4. | Cloning | clone() method of Cloneable interface allows to clone new Object so override clone() method and throw CloneNotSupportedException |
2. Singleton Object creation :
Although we have seen different ways to create Object and suppression technique but there must be one such Object available during application lifetime to use this class’ properties/behavior
Therefore, to create Singleton instance in Java there are different ways –
- Eager initialization
- Lazy initialization
- Enum Singleton
- Lazy initialization in a Single threaded environment
- Lazy initialization with double control lock in a multi-threaded environment
In this illustration, we will see how to create Singleton instance using lazy initialization technique in a multi-threaded environment
LoggerFactory.java
package in.bench.resources.singleton.design;
import java.io.Serializable;
public class LoggerFactory implements Serializable, Cloneable {
// serialization UID
private static final long serialVersionUID = 2251319696423032771L;
// member variable - lazy initialization
public static LoggerFactory LOGGER = null;
// 1. private constructor
private LoggerFactory() {
// 2. suppress object creation via Reflection API
if(null != LOGGER) {
throw new RuntimeException("Not allowed to create object via Reflection API");
}
}
// 3. suppressing object creation via de-serialization
public LoggerFactory readResolve() {
return LOGGER;
}
// 4. overriding clone() method to throw Exception
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* returns always singleton instance
* @return
*/
public static LoggerFactory getLogger() {
// for performance enhancement/improvement
if(null == LOGGER) {
// for multi-threaded environment
synchronized(LoggerFactory.class) {
// double control lock
if(null == LOGGER) {
// this piece of code will be executed only-once
LOGGER = new LoggerFactory();
return LOGGER;
}
}
}
return LOGGER;
}
}
Read how to create Singleton class in a single Thread environment
Related Articles :
- Java – Singleton design pattern, restricting all 4 ways of Object creation
- Java – How to construct a singleton class in a multi-threaded environment ?
References:
- https://www.benchresources.net/singleton-design-pattern-with-java-serialization/
- http://www.oracle.com/technetwork/articles/java/singleton-1577166.html
- http://www.javaworld.com/article/2074979/java-concurrency/double-checked-locking–clever–but-broken.html
Happy Coding !!
Happy Learning !!