– What is Singleton design pattern ?
– How to implement Singleton design pattern in java ?
– Effects of multithreading on singleton pattern
– Implementing Double checked locking for singleton
– Eager instantiation of singleton
– Ways of breaking singleton
– Uses of Singleton pattern
– Singleton pattern in Java EE
– Singleton as Anti-pattern
-Singleton is an EJB
Singleton Design Pattern
The Singleton pattern ensures that a class has only one instance and provides a global point of access to it.
Standard Singleton implementation
To ensure the class has only one instance, we mark the constructor has private. So, we can only instantiate this class from within the class.
We create a static variable that will hold the instance of the class.
Then, we create a static method that provides the instance of the singleton class. This method checks if an instance of the singleton class is available. It creates an instance, if its not available; Otherwise, it returns the available instance.
@Command
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Problem with the standard implementation code above
The standard singleton implementation code works fine in Single threaded environment.
But in multithreaded environment, the getInstance() code breaks :
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
If two threads enter the if condition at the same time, then two instances of Singleton will be created.
Handling Multithreading issue with standard singleton implementation
We can add synchronized keyword to the getInstance method signature and it would make the method synchronized. So, only one thread can access it at a time.
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
This solves the multithreading issue. But it is slow since only one thread can access getInstance() method at a time.
We can use following approaches for this :
1 : Double checked locking
In this approach, we first check if the instance is created. If not, we synchronize.
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
// first check if instance is available
if (instance == null) {
// if instance not available, enter synchronized block to create
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
This is an approach to handle multithreading issues with the standard implementation. However, this approach has issues as well. Read more about this in the comments section before using this.
2 : Eager instance creation
We can choose to create the instance of Singleton class when the class is loaded.
public class EagerSingleton {
// create instance eagerly
private static EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;// just return the instance
}
}
3 : Bill Pugh Singleton
This solution is considered better as it performs singleton instantiation when getInstance() is called.
public class BillPughSingleton {
private BillPughSingleton() {
}
private static class SingletonHelper {
private static final BillPughSingleton INSTANCE = new BillPughSingleton();
}
public static BillPughSingleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
4 : Creating Singleton using Enum
Enum is thread safe. We can implement Singleton through Enum so that the singleton will have only one instance even in a multithreaded environment.
public enum EnumSingleTon {
INSTANCE;
// add sinlgeton methods
public void method() {
System.out.println("SingleTon Method");
}
}
public class TestEnumSingleton {
public static void main(String[] args) {
EnumSingleTon.INSTANCE.method();
}
}
Using enums protects against deserialization and reflection. Also, Enum singletons are lazily initialized.
Enum based singleton is considered the best way to implement singletons. (Refer : Effective Java by Joshua Bloch)
Breaking Singleton questions you may get in interviews
Even though we avoided multiple instance creation of singleton class by using Double checked locking or Eager instance creation, instances can still be created by :
– cloning
– reflection
– Deserialization
– Sub-classing singleton class
How to avoid Singleton instance creation by cloning ?
We can create a copy of an object using clone() method.
To avoid creating a clone of our singleton class, we can do the following :
– Implement Cloneable interface
– Override the clone() method and throw CloneNotSupportedException from it.
How to avoid Singleton class instance creation through Reflection ?
To avoid instance creation through reflection, throw an exception from constructor if it already has an instance.
private Singleton() {
if( Singleton.instance != null ) {
throw new InstantiationError("Cannot create instance Singleton through reflection");
}
}
How to avoid singleton instance creation during deserialization ?
Avoid multiple singletons during deserialization using readResolve().
protected Object readResolve() {return instance;}
How to avoid a subclass creating singleton instance ?
If you just provide a private constructor, a subclass cannot instantiate it to create another instance. This is because the super constructor won’t be visible to the child class.
Uses of Singleton Design Pattern
Logger
Singleton pattern is a good option for the Logger class when we want to create one log file with the logged messages. If we have more than one instances of Logger in the application, a new log will be created with every instance.
Cache
We can use Singleton pattern to implement caches as that provides a single global access to it.
Implementing Singleton Pattern in Java EE
In Java EE, just by adding @Singleton annotation to a class, you can turn it into a singleton bean.
import javax.ejb.Singleton;
@Singleton
public class SingletonBean {
}
The @Singleton annotation marks the class as a singleton EJB, and the container handles creation and usage of the single instance.
Why singleton pattern is considered an Anti-pattern ?
– Singletons aren’t easy to handle with unit tests. You can’t control their instantiation and they may retain state across invocations.
Frameworks such as Spring control the lifecycle of their objects and often create singletons, but these objects are injected into their dependent objects by the framework. Thus the codebase itself doesn’t treat the objects as singletons.
– In multithreaded environment, access to the singleton object may have to be guarded (e.g. via synchronisation).
Singleton is an EJB
http://www.mastertheboss.com/javaee/ejb-3/singleton-ejb-tutorial