Bill Pugh: Initialization-on-demand singleton in Java

UPDATED: 24 July 2016
Singleton
The singleton pattern is a design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.

Initialization-on-demand singleton by Bill Pugh
Its one of the concrete way of creating singleton class in Java. We will understand it with example.

Source code
/**
 * Example: Singleton by Bill Pugh.
 *
 * @author javaQuery
 * @date 24th July, 2016
 * @Github: https://github.com/javaquery/Examples
 */
public class SingletonBillPugh {

    /* private constructor */
    private SingletonBillPugh() {
    }

    /* static inner class */
    private static class LazyHolder{
        private static final SingletonBillPugh INSTANCE = new SingletonBillPugh();
    }
    
    /* get instance of SingletonBillPugh */
    public static SingletonBillPugh getInstance(){
        return LazyHolder.INSTANCE;
    }
}
Explanation
Now lets understand why its Initialization-on-demand (Initialize only when we call getInstance() method).

Java Language Specification
12.4.1 When Initialization Occurs (https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.1)
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

12.4.1.1: T is a class and an instance of T is created.
12.4.1.2: A static method declared by T is invoked.
12.4.1.3: A static field declared by T is assigned.
...
When class SingletonBillPugh is loaded by JVM, the class follows initialization process specified in Java Language Specification(12.4.1). Since the class does not have any static variables to initialize(12.4.1.3) the initialization completed.

What happen to class LazyHolder?
According to Java Language Specification (8.1.3) for inner class whose declaration does not occur in a static context of SingletonBillPugh. Inner class LazyHolder is not initialized until it it executed.

Java Language Specification
8.1.3. Inner Classes and Enclosing Instances (https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3)

When an inner class (whose declaration does not occur in a static context) refers to an instance variable that is a member of a lexically enclosing type declaration, the variable of the corresponding lexically enclosing instance is used.

What happen to method getInstance?
According to 12.4.1.2 A static method declared by T is invoked(called).


12.4.2. Detailed Initialization Procedure (https://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2)
In first paragraph "Java Virtual Machine is responsible for taking care of synchronization and recursive initialization"
So when class SingletonBillPugh is initializing through LazyHolder, no other thread can initialize class until previous initialization of class SingletonBillPugh finish. And we marked variable INSTANCE final so other initialization won't happen. SingletonBillPugh class is completely singleton when using Bill Pugh singleton pattern.


0 comments :