Search This Blog

Wednesday, August 6, 2008

Singleton and Lazy Initialization

Instantiating a Singleton lazily has always been a challenge in pre JDK1.5.X days due to semantics of the volatile modifier and/or synchronization penalties. The double checked locking has been discussed quite a bit. I found this one technique of lazily loading a singleton that I thought I'd share. I must admit, I am late in realizing the same :-(. In lawers terms, if this has been "Asked and answered", too bad! There must be a few slow people like me out there...:-), hopefully ;-) The principle used is the "Lazy initialization holder class idiom", JLS 12.4.1.

The singleton class has a Holder class which creates the Singleton instance as shown below:

public class Singleton { 
static {
Watcher.singletonLoaded = true;
}

/**
* Prevent instantiation.
*/

private Singleton() {}

/**
* @return Lazily loaded instance.
*/

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

private static final class SingletonHolder {
static {
Watcher.singletonHolderLoaded = true;
}
public static final Singleton INSTANCE = new Singleton();
}
}


In the above code when Singleton.instance() is invoked for the first time, the side effect of loading the HolderClass and the creation of the Singleton INSTANCE occurs.

This is kinda nice as there is no synchronization and depends on the fact that class loading is serial, i.e., two threads will not load the same class twice with the same class loader at the same time.

The Watcher class shown above is only a simple way to track when the class has been loaded.

The following represent some unit test that demonstrate when the class is loaded and when the Singleton is obtained.
public class SingletonTest { 
@Test public void test() throws ClassNotFoundException {
Class.forName("Singleton");

assertTrue("Singleton class must have been loaded", Watcher.singletonLoaded);
assertFalse("Single Holder should not have been loaded", Watcher.singletonHolderLoaded);

Singleton.instance();

assertTrue("Singleton Holder must have been loaded", Watcher.singletonHolderLoaded);
}
}


The Watcher class shown above is a simple static class with booleans as indicators.

No comments: