If you're talking about threadsafe, lazy initialization of the singleton, here is a cool code pattern to use that accomplishes 100% threadsafe lazy initialization without any synchronization code:
public class MySingleton {
private static class MyWrapper {
static MySingleton INSTANCE = new MySingleton();
}
private MySingleton () {}
public static MySingleton getInstance() {
return MyWrapper.INSTANCE;
}
}
This will instantiate the singleton only when getInstance()
is called, and it's 100% threadsafe! It's a classic.
It works because the class loader has its own synchronization for handling static initialization of classes: You are guaranteed that all static initialization has completed before the class is used, and in this code the class is only used within the getInstance()
method, so that's when the class loaded loads the inner class.
As an aside, I look forward to the day when a @Singleton
annotation exists that handles such issues.
Edited:
A particular disbeliever has claimed that the wrapper class "does nothing". Here is proof that it does matter, albeit under special circumstances.
The basic difference is that with the wrapper class version, the singleton instance is created when the wrapper class is loaded, which when the first call the getInstance()
is made, but with the non-wrapped version - ie a simple static initialization - the instance is created when the main class is loaded.
If you have only simple invocation of the getInstance()
method, then there is almost no difference - the difference would be that all other sttic initialization would have completed before the instance is created when using the wrapped version, but this is easily dealt with by simply having the static instance variable listed last in the source.
However, if you are loading the class by name, the story is quite different. Invoking Class.forName(className)
on a class cuasing static initialization to occur, so if the singleton class to be used is a property of your server, with the simple version the static instance will be created when Class.forName()
is called, not when getInstance()
is called. I admit this is a little contrived, as you need to use reflection to get the instance, but nevertheless here's some complete working code that demonstrates my contention (each of the following classes is a top-level class):
public abstract class BaseSingleton {
private long createdAt = System.currentTimeMillis();
public String toString() {
return getClass().getSimpleName() + " was created " + (System.currentTimeMillis() - createdAt) + " ms ago";
}
}
public class EagerSingleton extends BaseSingleton {
private static final EagerSingleton INSTANCE = new EagerSingleton();
public static EagerSingleton getInstance() {
return INSTANCE;
}
}
public class LazySingleton extends BaseSingleton {
private static class Loader {
static final LazySingleton INSTANCE = new LazySingleton();
}
public static LazySingleton getInstance() {
return Loader.INSTANCE;
}
}
And the main:
public static void main(String[] args) throws Exception {
// Load the class - assume the name comes from a system property etc
Class<? extends BaseSingleton> lazyClazz = (Class<? extends BaseSingleton>) Class.forName("com.mypackage.LazySingleton");
Class<? extends BaseSingleton> eagerClazz = (Class<? extends BaseSingleton>) Class.forName("com.mypackage.EagerSingleton");
Thread.sleep(1000); // Introduce some delay between loading class and calling getInstance()
// Invoke the getInstace method on the class
BaseSingleton lazySingleton = (BaseSingleton) lazyClazz.getMethod("getInstance").invoke(lazyClazz);
BaseSingleton eagerSingleton = (BaseSingleton) eagerClazz.getMethod("getInstance").invoke(eagerClazz);
System.out.println(lazySingleton);
System.out.println(eagerSingleton);
}
Output:
LazySingleton was created 0 ms ago
EagerSingleton was created 1001 ms ago
As you can see, the non-wrapped, simple implementation is created when Class.forName()
is called, which may be before the static initialization is ready to be executed.