Singleton Design Pattern in Java
Singleton Class in Java — Complete Guide
What is a Singleton Class?
A Singleton class in Java is a design pattern that ensures:
-
Only one instance of the class exists in the entire JVM.
-
It provides a global point of access to that instance.
Example use cases:
-
Database connections
-
Logger classes
-
Configuration managers
-
Thread pools
-
Caches
Why Use Singleton?
-
To control resource usage (only one instance instead of multiple).
-
To avoid inconsistent state (since only one object exists).
-
To share data easily between different parts of the application.
Rules for Singleton Class
-
Constructor must be private (so no one can create an instance directly).
-
Class must have a static instance variable of itself.
-
Must provide a public static method that returns the single instance.
Ways to Create Singleton in Java
There are 5 common ways to implement a Singleton pattern in Java:
Eager Initialization (Simple & Fast)
public class SingletonEager {
private static final SingletonEager instance = new SingletonEager();
private SingletonEager() {
// private constructor
}
public static SingletonEager getInstance() {
return instance;
}
}
Advantages:
-
Simple and thread-safe (because instance created during class loading)
Disadvantages:
-
Instance created even if not used (wastes memory)
Lazy Initialization (Created When Needed)
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
Advantages:
-
Instance created only when required
Disadvantages:
-
Not thread-safe (multiple threads can create multiple instances)
Thread-Safe Singleton (Synchronized Method)
public class SingletonThreadSafe {
private static SingletonThreadSafe instance;
private SingletonThreadSafe() {}
public static synchronized SingletonThreadSafe getInstance() {
if (instance == null) {
instance = new SingletonThreadSafe();
}
return instance;
}
}
Advantages:
-
Thread-safe
Disadvantages:
-
Synchronized method reduces performance (slow in multi-threaded apps)
Double-Checked Locking (Best Performance)
public class SingletonDoubleCheck {
private static volatile SingletonDoubleCheck instance;
private SingletonDoubleCheck() {}
public static SingletonDoubleCheck getInstance() {
if (instance == null) {
synchronized (SingletonDoubleCheck.class) {
if (instance == null) {
instance = new SingletonDoubleCheck();
}
}
}
return instance;
}
}
Advantages:
-
Thread-safe and high performance
-
Instance created lazily
Recommended for most production use cases
Bill Pugh Singleton (Best Modern Way)
public class SingletonBillPugh {
private SingletonBillPugh() {}
private static class Helper {
private static final SingletonBillPugh INSTANCE = new SingletonBillPugh();
}
public static SingletonBillPugh getInstance() {
return Helper.INSTANCE;
}
}
Advantages:
-
Thread-safe
-
Lazy-loaded
-
No synchronization overhead
Most efficient and recommended approach
Enum Singleton (Simplest & Serialization Safe)
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
System.out.println("Doing something...");
}
}
Advantages:
-
Thread-safe
-
Serialization & reflection safe
-
Simple syntax
Best for single-instance services (like loggers, managers)
Preventing Reflection & Serialization Issues
Reflection can break singleton by invoking private constructor:
To prevent this, throw an exception inside the constructor if instance already exists:
For serialization, implement readResolve():
Comments (0)
Leave a Comment