Advanced Java September 20 ,2025

Singleton Design Pattern in Java

Introduction

The Singleton Pattern is one of the simplest but most widely used creational design patterns. Its primary purpose is to ensure that a class has only one instance while providing a global point of access to that instance.

In real-world terms:

  • Imagine a President of a country or a Central Bank. There can be only one at a time, and everyone refers to that single entity.
  • Similarly, in software, some classes must have exactly one instance — for example, a configuration manager, logging service, or database connection pool.

Problem Statement

Consider a logging class:

public class Logger {
    public void log(String message) {
        System.out.println(message);
    }
}

If every class in your application creates its own Logger object:

Logger logger1 = new Logger();
Logger logger2 = new Logger();

Problems arise:

  1. Multiple instances exist — consuming unnecessary memory.
  2. Inconsistent state — configuration or log files could be different for each instance.
  3. Difficult coordination — you may want a single centralized logger for uniform logging.

The Singleton Pattern solves this by ensuring only one instance exists throughout the application.

Implementation in Java

1. Eager Initialization

The simplest approach is to create the instance when the class loads.

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

    // Private constructor prevents external instantiation
    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }

    public void showMessage() {
        System.out.println("Hello from EagerSingleton!");
    }
}

// Usage
public class Main {
    public static void main(String[] args) {
        EagerSingleton singleton = EagerSingleton.getInstance();
        singleton.showMessage();
    }
}

Advantages:

  • Simple and thread-safe.
  • Instance is ready to use when needed.

Disadvantages:

  • Object is created even if it’s never used (wasteful for heavy resources).

2. Lazy Initialization

The instance is created only when it’s first requested.

public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

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

    public void showMessage() {
        System.out.println("Hello from LazySingleton!");
    }
}

Advantages:

  • Saves resources by creating the instance only when needed.

Disadvantages:

  • Not thread-safe in multi-threaded environments. Multiple threads could create multiple instances simultaneously.

3. Thread-Safe Singleton (Synchronized)

To handle multi-threaded scenarios:

public class ThreadSafeSingleton {
    private static ThreadSafeSingleton instance;

    private ThreadSafeSingleton() {}

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

    public void showMessage() {
        System.out.println("Hello from ThreadSafeSingleton!");
    }
}

Advantages:

  • Safe for concurrent access.

Disadvantages:

  • synchronized adds performance overhead every time getInstance() is called.

4. Double-Checked Locking (Optimized Thread-Safe)

Combines lazy initialization with thread safety without heavy overhead.

public class DoubleCheckedSingleton {
    private static volatile DoubleCheckedSingleton instance;

    private DoubleCheckedSingleton() {}

    public static DoubleCheckedSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckedSingleton.class) {
                if (instance == null) {
                    instance = new DoubleCheckedSingleton();
                }
            }
        }
        return instance;
    }

    public void showMessage() {
        System.out.println("Hello from DoubleCheckedSingleton!");
    }
}

Key Point: volatile ensures visibility of changes across threads.

Advantages:

  • Thread-safe.
  • Efficient performance after first initialization.

5. Bill Pugh Singleton (Using Inner Static Class)

A modern, clean approach without synchronization overhead:

public class BillPughSingleton {
    private BillPughSingleton() {}

    // Inner static class holds the singleton instance
    private static class SingletonHelper {
        private static final BillPughSingleton INSTANCE = new BillPughSingleton();
    }

    public static BillPughSingleton getInstance() {
        return SingletonHelper.INSTANCE;
    }

    public void showMessage() {
        System.out.println("Hello from BillPughSingleton!");
    }
}

Advantages:

  • Thread-safe without synchronized.
  • Lazy-loaded only when getInstance() is called.

Real-World Analogy

  • Database Connection Pool: You want only one pool managing all connections.
  • Configuration Manager: One centralized object holds all app settings.
  • Logging Service: One instance handles all logging across modules.

Advantages of Singleton Pattern

  1. Controlled Access: Only one instance exists.
  2. Memory Efficiency: Reduces overhead by reusing a single object.
  3. Global Access: Can be accessed from anywhere in the program.
  4. Thread Safety: With proper implementation, ensures safe multi-threaded access.
  5. Consistency: Shared state across the application.

Disadvantages

  1. Testing Difficulty: Singletons are hard to mock in unit tests.
  2. Hidden Dependencies: Overuse can lead to tightly coupled code.
  3. Global State: Can become similar to global variables if misused.

When to Use

  • When exactly one instance of a class is required.
  • When the instance should be globally accessible.
  • For resources that are expensive to create (database connections, configuration objects, logging services).

Conclusion

The Singleton Pattern is a cornerstone of creational design patterns. It provides a single point of access and ensures consistency, memory efficiency, and controlled object creation.

In Java, there are multiple ways to implement a Singleton — Eager Initialization, Lazy Initialization, Thread-Safe, Double-Checked Locking, and Bill Pugh Inner Static Class. The choice depends on resource needs, performance, and thread safety requirements.

Next, we can explore the Prototype Design Pattern, which allows creating object copies instead of instantiating new ones, saving resources and improving performance.

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Multi...
Advanced Java August 08 ,2025

Java Multithreading...

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

How Concur...
Advanced Java October 10 ,2025

How ConcurrentHashMa...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Semaphore...
Advanced Java October 10 ,2025

Semaphore in Java

ExecutorSe...
Advanced Java October 10 ,2025

ExecutorService in J...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Producer-C...
Advanced Java October 10 ,2025

Producer-Consumer Pr...

Implementi...
Advanced Java October 10 ,2025

Implementing a Custo...

Busy Spin
Advanced Java October 10 ,2025

Busy Spin

Serializat...
Advanced Java October 10 ,2025

Serialization and De...

Segment Lo...
Advanced Java October 10 ,2025

Segment Locking in J...

Tree Bins...
Advanced Java October 10 ,2025

Tree Bins in Java

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com