1. Definition
Definition in wikipedia
2. What use is singleton pattern?
There are many objects we only need one of: thread pools, caches, dialog boxes, objects that preferences and registry settings, objects used for logging, and objects that act as device derivers to devices like printers and graphics cards. In fact, for many of these types of objects, if we were to instantiate more than one we’d run into all sorts of problems like incorrect program behivior, overuse of resource, or inconsistent results.
3. How singleton pattern achieve this?
- Hide the constructor of the class.
- Define a public static operation
getInstance()
that returns the sole instance of the class.
4. Implementation singleton pattern
The lazy initialization is shown as follows.
public class Singleton {
private static Singleton SINGLETON;
private Singleton () {
System.out.println("An only-one object is created.");
}
public static Singleton getInstance() {
if (SINGLETON == null)
SINGLETON = new Singleton();
return SINGLETON;
}
}
// Test if we can create only one object
public class SingletonTest {
public static void main(String[] args) {
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
}
}
// Result is :
//An only-one object is created.
Considering multithreading, we should make getInstance()
a synchronized method.
public static synchronized Singleton getInstance() {
if (SINGLETON == null)
SINGLETON = new Singleton();
return SINGLETON;
}
Actually, the above code is not quite good. The only time synchronizatino is relevant is the first time through this method. Say once we’ve set the SINGLETON
varialbe to an instance of SINGLETON
, we have no further to synchronize this method. After the first time through, synchronization is totally unneeded overhead!
Improved methods:
We have a few options to solve this.
Do nothing if the performance of
getInstance()
is not critical to the application.**Move to an eagerly created instance rather than a lazily created one.Likt this,
public class Singleton { private static Singleton SINGLETON = new Singleton(); private Singleton(){} public static Singleton getInstance() { return SINGLETON; } }
Using this appreach, we rely on JVM to create the unique instance of Singleton when the class is loaded. The JVM guarantees that the instance will be created before any thread accesses the static SINGLETON
variable.
- User “double-checked locking” to reduce the use of synchronization in
getInstance()
public class Singleton {
private volatile static Singleton SINGLETON;
private static Object lock = new Object();
private Singleton(){}
public static Singleton getInstance() {
if (SINGLETON == null) {
synchronized (lock) {
if (SINGLETON == null)
SINGLETON = new Singleton();
}
}
return SINGLETON;
}
}
The volatile keyword ensures that multiple threads handle the SINGLETON
variable correctly when it is being initialized to the Singleton
instance.
Unfortunately, this method is broken under JDK 1.4 and lower because volatile usage and semantics.
5. Implementation singleton pattern through inner class
By using static inner nested class
in Java to ensure on-demand loading, we can also create a singleton object. This is Thread-safe as initialization is done on-demand. There is no need for any synchronization. It’s also a lazy initialization method.
public class Singleton {
private static class Hodler {
private static final Singleton instance = new Singleton();
}
private Singleton(){}
public static Singleton getInstance() {
return Hodler.instance;
}
}
6. Conclusion
- The Singleton Pattern ensures you have at most one instance of a class in your application.
- The Singleton Pattern also provides a global access point to that instance.
- Java’s implementation of the Singleton Pattern makes use of a private constructor, a static method combined with a static variable.