The singleton pattern ensures that a class has only one instance and provides a global access point.
In Java, there are several common methods to implement the singleton pattern.
Eager Initialization#
The eager initialization creates an instance when the class is loaded, making it thread-safe but potentially wasting memory.
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
// Private constructor to prevent external instantiation
private Singleton() {}
// Provide a global access point
public static Singleton getInstance() {
return INSTANCE;
}
}
Lazy Initialization (Not Thread-Safe)#
The lazy initialization creates an instance only when getInstance()
is called for the first time, making it not thread-safe.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Lazy Initialization (Thread-Safe)#
By using synchronized methods, it ensures that there is only one instance even in a multi-threaded environment.
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Double-Checked Locking#
It checks whether an instance has been created both inside and outside the synchronized block, reducing synchronization overhead.
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Static Inner Class#
Using a static inner class ensures thread safety and lazy loading.
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
Enum#
The simplest implementation, recommended to use. It is thread-safe, supports serialization, and prevents reflection attacks.
public enum Singleton {
INSTANCE;
public void someMethod() {
// Instance method
}
}