Singleton Pattern in Java


The Singleton Pattern

The Singleton Pattern ensures that a class has only one instance and provides a global point of access to it. It’s one of the most commonly used design patterns in Java.

☝️ Why Use Singleton?
  • To control access to resources (e.g., configuration, logging, DB connections)
  • Ensures consistency with a single shared instance
  • Reduces memory footprint when a single object is reused
✅ Ways to Implement Singleton in Java
🔹 1. Eager Initialization

Instance is created at the time of class loading.


public class Singleton {
    private static final Singleton instance = new Singleton();

    private Singleton() {}  // private constructor

    public static Singleton getInstance() {
        return instance;
    }
}

Pros: Simple, thread-safe
Cons: Instance created even if not used

🔹 2. Lazy Initialization (Non-thread-safe)

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Pros: Instance created only when needed
Cons: Not thread-safe

🔹 3. Thread-safe Lazy Initialization (Synchronized)

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

Pros: Thread-safe
Cons: Slight performance hit due to synchronized method

🔹 4. Double-Checked Locking with Volatile (Best of Both Worlds)

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;
    }
}

Pros: High performance, lazy loaded, thread-safe
Recommended for most use cases

🔹 5. Bill Pugh Singleton (Using Static Inner Class)

public class Singleton {
    private Singleton() {}

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

Pros: Thread-safe, lazy initialization, no synchronization overhead
Very efficient and widely recommended

🔹 6. Enum Singleton (Best Practice)

public enum Singleton {
    INSTANCE;

    public void doSomething() {
        System.out.println("Doing something...");
    }
}

Pros: Thread-safe, protects against serialization & reflection attacks
Cons: Not suitable if your singleton must extend a class

✅ Summary of Approaches
Approach Thread-safe Lazy Recommended
Eager Initialization ✔️ Simple cases
Lazy Initialization ✔️ ❌ Not safe
Synchronized Method ✔️ ✔️ Okay
Double-Checked Locking ✔️ ✔️ 👍 Yes
Static Inner Class ✔️ ✔️ 👍 Yes
Enum ✔️ ✔️ 👍 Best practice