The Singleton Pattern ensures a class has only one instance, and provides a global point of access to it.
Here the implementation of this definition :
public class Singleton {
/** The unique instance **/
private static Singleton instance;
/** The private constructor **/
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
There is a problem with the code above in a multithreaded environment. Two threads might get ahold of two different instances if they enter at same time in the getInstance method.
So how to deal with multithreading ?
This problem can be fixed using the synchronized keyword.
public class Singleton {
/** The unique instance **/
private static Singleton instance;
/** The private constructor **/
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
The getInstance method is now synchronized so we force every threads to wait its turn before it can enter the method. This solution fixes our problem but it is very expensive. Indeed we only need synchronization for the first call. After that synchronization is totally unneeded. Remember that synchronization decreases performance by a factor of 100.
A solution consists of relying on the JVM to create our instance when the class is loaded. You can use this solution if the overhead of the creation and runtime aspects of the singleton are not onerous.
Since Java 1.5, there is a new approach to implement Singletons. Simply make it an enum type :
public class Singleton {
/** The unique instance **/
private static Singleton instance = new Singleton();
/** The private constructor **/
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
Accessing the enum singleton :
public enum Singleton {
INSTANCE;
//Singleton method
public void someMethod( ) {...}
}
Singleton.INSTANCE.someMethod( );
If you don't want to automatically create an instance of your singleton when the JVM start, there is another solution called "double-checked locking". With this solution, we first check to see if an instance is created and only then we synchronize. This way we only synchronize the first call and there's no performance issue anymore. Another requirement is to use the volatile keyword for the Singleton instance.
public class Singleton {
/** The unique instance **/
private volatile static Singleton instance;
/** The private constructor **/
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
!!! This solution will not work in Java 1.4 or earlier. Many JVMs in Java version 1.4 and earlier contains implementation of the volatile keyword that allow improper synchronization fo double checed locking.
Here's an interresting article on the double-checked locking pattern and the use of the volatile keyword.
Another article in french.