Definition
- A class has only one instance
- And provide a global point of access to it
Motivation
- Sometimes we want just a single instance of a class to exist in the system.
- For example, we want just one factory for a family of products.
- We need to have that one instance easily accessible.
- And we want to ensure that additional instances of the class cannot be created.
Code Sample
Singleton.java ( THREAD UNSAFE )
public class Singleton {
private static Singleton firstInstance = null;
/**
* The Singleton
Constructor.
* Note that it is
private.
* No client can instantiate a Singleton object directly!
*/
private Singleton() {
}
/**
* Returns a reference to the single instance.
* Creates the instance if it does not yet
exist.
* This is called lazy instantiation.
*/
public static Singleton
getInstance() {
if (firstInstance == null) {
firstInstance = new Singleton();
}
return firstInstance;
}
}
THREAD SAFE version 1
- Not Recommended
- Restricts only one thread to be able to access the method at a time which slows down the performance
public class Singleton {
private static Singleton firstInstance = null;
private Singleton() {
}
public static synchronized Singleton
getInstance() {
if (firstInstance == null) {
firstInstance = new Singleton();
}
return firstInstance;
}
}
THREAD SAFE version 2
- Double-checked locking
- The method is forced to be synchronized until the first instance is created
public class Singleton {
private static Singleton firstInstance = null;
private Singleton() {
}
public static Singleton
getInstance() {
if (firstInstance == null) {
synchronized (Singleton.class) {
if (firstInstance == null) {
firstInstance = new Singleton();
}
}
}
return firstInstance;
}
}
THREAD SAFE version 3
- Inner class approach
- Initialization-on-demand holder
- The nested class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called (thus thread safe)
public class Singleton {
private Singleton() {
}
/**
* Initializes
singleton.
*
* SingletonHolder is
loaded on the first execution of Singleton.getInstance()
* or the first access
to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton
getInstance() {
return SingletonHolder.INSTANCE;
}
}