Home/Learn/Java A–Z/Singleton Pattern

Singleton Pattern

Intermediate
Design Patterns

Singleton ensures a class has exactly one instance. Java offers several implementations — from simple to thread-safe and serialization-safe.

Overview

Singleton is one of the most discussed design patterns in Java interviews. The basic idea is simple — one instance, global access — but correct implementation requires handling thread safety, serialization, and reflection attacks. The enum singleton is the recommended modern approach. In Spring applications, beans are singletons by default, eliminating the need to implement the pattern manually.

Thread-Safe Singleton Implementations

There are several approaches, each with trade-offs:

1. Eager initialisation — simple, thread-safe, but creates instance at class load even if never used. 2. Lazy with synchronized — thread-safe, but synchronized on every access is slow. 3. Double-checked locking — fast and thread-safe with volatile (Java 5+). 4. Initialization-on-demand holder — elegant lazy loading via class loading guarantee.

SingletonImpls.java
// 1. Eager initialization (simple, safe)
public class EagerSingleton {
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    private EagerSingleton() {}
    public static EagerSingleton getInstance() { return INSTANCE; }
}

// 2. Double-checked locking (lazy + fast)
public class DCLSingleton {
    private static volatile DCLSingleton instance;
    private DCLSingleton() {}
    public static DCLSingleton getInstance() {
        if (instance == null) {
            synchronized (DCLSingleton.class) {
                if (instance == null) {         // second check
                    instance = new DCLSingleton();
                }
            }
        }
        return instance;
    }
}

// 3. Initialization-on-demand holder (preferred lazy)
public class HolderSingleton {
    private HolderSingleton() {}
    private static class Holder {
        static final HolderSingleton INSTANCE = new HolderSingleton();
    }
    public static HolderSingleton getInstance() {
        return Holder.INSTANCE; // class loaded lazily
    }
}

Enum Singleton (Recommended)

Enum singleton is the simplest, most robust implementation. It is thread-safe, serialisation-safe (JVM guarantees single instance across serialisation), and protected against reflection attacks.

Joshua Bloch (Effective Java) recommends this as the best singleton implementation.

EnumSingleton.java
// Enum singleton — recommended approach
public enum DatabaseConnection {
    INSTANCE;

    private final Connection conn;

    DatabaseConnection() {
        // initialised once by JVM
        this.conn = createConnection();
    }

    private Connection createConnection() {
        // expensive DB connection setup
        return DriverManager.getConnection("jdbc:...");
    }

    public Connection getConnection() { return conn; }

    public void executeQuery(String sql) {
        // ...
    }
}

// Usage — no getInstance() needed
DatabaseConnection.INSTANCE.executeQuery("SELECT 1");
Connection conn = DatabaseConnection.INSTANCE.getConnection();

Singleton in Spring

In Spring, all beans are singletons by default within the application context — you get the same instance every time you inject a bean. You do not need to implement the Singleton pattern yourself.

Spring manages the singleton lifecycle, thread safety of the container, and handles destruction (DisposableBean / @PreDestroy). Singleton scope is different from prototype scope which creates a new instance per injection.

SpringSingleton.java
// Spring-managed singleton (default scope)
@Service
public class UserService {
    // Spring creates one instance and injects it everywhere
    @Autowired
    private UserRepository repo;

    public List<User> findAll() {
        return repo.findAll();
    }
}

// Explicit scope annotations
@Component
@Scope("singleton")  // default — same as no annotation
class SingletonBean {}

@Component
@Scope("prototype")  // new instance per injection
class PrototypeBean {}

// Bean singleton vs GoF Singleton:
// Spring singleton = one instance per ApplicationContext
// GoF Singleton    = one instance per ClassLoader

Key Points to Remember

  • Enum singleton is the most robust: thread-safe, serialisation-safe, reflection-safe.
  • Double-checked locking requires volatile — without it, partially-constructed instances can be observed.
  • Initialization-on-demand holder pattern provides thread-safe lazy loading elegantly.
  • All Spring beans are singletons by default — implement the pattern manually only outside Spring.
  • Singleton is often considered an anti-pattern in testing because it introduces global state.

Practice Singleton Pattern in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

Why is volatile required in the double-checked locking singleton?

HardAmazon
2

Why is enum the best way to implement Singleton in Java?

MediumGoogle
3

How can serialisation break a Singleton and how do you prevent it?

HardOracle
4

How can reflection break a Singleton?

HardMicrosoft
5

What is the difference between Spring singleton scope and GoF Singleton pattern?

MediumPivotal

Ask Aria about Singleton Pattern

Your personal AI tutor — ask anything about this concept