Singleton Pattern – Best Practices In Java – Lazy, Thread-Safe and Non-Locking

You might be aware of what a Singleton Pattern is, already but here i’m repeating its definition anyway.

Note: Code snippets are copied from wikipedia.

Singleton Pattern

Ensure a class has only one instance and provide a global point of access to it.

UML

singleton-pattern

 

Comparison of Singleton Implementations

 

Implementation Type Lazy Thread-Safe Non-Locking Easy to Understand/ Implement
The Enum Way Yes Yes Yes Yes
Initialization-on-demand holder idiom Yes Yes Yes Yes
Eager or Static Block Initialization No Yes Yes Yes
Lazy Synchronized Initialization Yes Yes No Yes
Double Checked Locking Lazy Initialization Yes Yes Yes No

 

Best Practices

The Enum way

An enum with only one value.

public enum Singleton {
INSTANCE;

public String method1(String arg1) {
return arg1;
}

public String method2(String arg1, String arg2) {
return arg1 + arg2;
}

private Singleton() {
System.out.println("Am I lazy?");
}
}

====================================
public class App {
public static void main(String[] args) {
System.out.println(Singleton.class.getName());
System.out.println("Hello World!");
System.out.println(Singleton.INSTANCE.method1("method1-arg1"));
System.out.println(Singleton.INSTANCE.method2("method2-arg1", "method2-arg2"));
}
}
====================================
Output:
com.haris.poc.Singleton
Hello World!
Am I lazy?
method1-arg1
method2-arg1method2-arg2

Initialization-on-demand holder idiom

public final class Singleton {
// Private constructor. Prevents instantiation from other classes.
private Singleton() { }

/**
* Initializes singleton.
*
* {@link SingletonHolder} is loaded on the first execution of {@link Singleton#getInstance()} or the first access to
* {@link SingletonHolder#INSTANCE}, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}

public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}

Other Common Practices

Eager or Static Block Initialization

public final class Singleton {
private static final Singleton INSTANCE = new Singleton();

private Singleton() {}

public static Singleton getInstance() {
return INSTANCE;
}
}

Lazy Synchronized Initialization

public final class SingletonDemo {
private static SingletonDemo instance = null;
private SingletonDemo() { }

public static synchronized SingletonDemo getInstance() {
if (instance == null) {
instance = new SingletonDemo();
}

return instance;
}
}

Double Checked Locking Lazy Initialization

Mind the ‘volatile’ keyword.

public final class SingletonDemo {
private static volatile SingletonDemo instance;
private SingletonDemo() { }

public static SingletonDemo getInstance() {
if (instance == null ) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}

return instance;
}
}

Breaking Singleton Interview Questions:

You can break Singleton Pattern by any of the following:

  1. Cloning – Implement Cloneable interface and throw CloneNotSupportedException from clone() method.
  2. 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");
    }
    }
    
  3. Deserialization – Avoid multiple singletons during deserialization using readResolve().
    protected Object readResolve() {return instance;}
    
  4. Sub-classing Singleton Class – Make the class final and Constructor private.

Leave a Reply

Your email address will not be published. Required fields are marked *

Connect with Facebook

*