This post demonstrates the proper implementation of Singleton Pattern
in Java
. Most of us would apply Singleton Pattern
in the most convenient way for us but not the proper implementation. In most cases, our codes would work. But when we deal with concurrency stuff and mission-critical applications, subtle issues may arise that are really hard to debug and figure out the root cause of.
What most people do
What’s wrong with the following codes? Well, a call to getInstance()
is expensive as it is synchronized
even after an instance of the class has been created and can impact performance.
[wp_ad_camp_1]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.turreta.ocp.designpatterns; public class SingletonDemo01 { private static SingletonDemo01 instance; private SingletonDemo01() { } public static synchronized SingletonDemo01 getInstance() { if(instance == null) { instance = new SingletonDemo01(); } return instance; } } |
The Proper Implementation
In this implementation, we first check if instance
is null
. If it’s true
, only then we apply synchronization on the class while creating an instance of the same class. Subsequent call to getInstance()
is not synchronized and therefore will not impact performance.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
package com.turreta.ocp.designpatterns; public class SingletonDemo02 { private static volatile SingletonDemo02 instance; private SingletonDemo02() { } public static SingletonDemo02 getInstance() { if(instance == null) { synchronized(SingletonDemo02.class) { instance = new SingletonDemo02(); } } return instance; } } |
[wp_ad_camp_2]
The usage of volatile
is to prevent subtle cases where the compiler performs optimization on the codes such that the object is accessed before it is completely constructed.