Java Singleton Pattern

Creational pattern ensuring only one instance of a class exists

java (1.0+) 2025-11-03 singleton design-pattern creational

Description

The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. It’s useful when exactly one object is needed to coordinate actions across the system.

Key Characteristics

  • Single instance: Only one instance of the class exists
  • Global access: Provides a global point of access
  • Lazy initialization: Instance created when first needed (optional)
  • Thread safety: Must be safe in multithreaded environments

Implementation Approaches

  • Eager initialization: Instance created at class loading time
  • Lazy initialization: Instance created on first access
  • Double-checked locking: Thread-safe lazy initialization
  • Bill Pugh solution: Uses inner static class (recommended)
  • Enum singleton: Simplest and most thread-safe

When to Use

  • Need exactly one instance of a class
  • Global access point needed
  • Resource management (database connections, file systems)
  • Logging, configuration, caching

Thread Safety Considerations

  • Simple lazy initialization is NOT thread-safe
  • Use synchronization or double-checked locking
  • Enum singleton is inherently thread-safe
  • Bill Pugh solution is thread-safe without synchronization overhead

Code

RAW
// Eager initialization (thread-safe)public class EagerSingleton {    private static final EagerSingleton instance = new EagerSingleton();        private EagerSingleton() {        // Private constructor prevents instantiation    }        public static EagerSingleton getInstance() {        return instance;    }}// Lazy initialization (NOT thread-safe)public class LazySingleton {    private static LazySingleton instance;        private LazySingleton() {}        public static LazySingleton getInstance() {        if (instance == null) {            instance = new LazySingleton();        }        return instance;    }}// Thread-safe lazy initialization with synchronizedpublic class SynchronizedSingleton {    private static SynchronizedSingleton instance;        private SynchronizedSingleton() {}        public static synchronized SynchronizedSingleton getInstance() {        if (instance == null) {            instance = new SynchronizedSingleton();        }        return instance;    }}// Double-checked locking (thread-safe)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;    }}// Bill Pugh solution (recommended - thread-safe, lazy)public class BillPughSingleton {    private BillPughSingleton() {}        private static class SingletonHelper {        private static final BillPughSingleton instance = new BillPughSingleton();    }        public static BillPughSingleton getInstance() {        return SingletonHelper.instance;    }}// Enum singleton (simplest, thread-safe, serializable)public enum EnumSingleton {    INSTANCE;        public void doSomething() {        // Singleton methods here    }}
RAW
// Eager singletonEagerSingleton eager1 = EagerSingleton.getInstance();EagerSingleton eager2 = EagerSingleton.getInstance();System.out.println(eager1 == eager2); // true - same instance// Lazy singleton (not thread-safe)LazySingleton lazy1 = LazySingleton.getInstance();LazySingleton lazy2 = LazySingleton.getInstance();System.out.println(lazy1 == lazy2); // true - same instance// Thread-safe singletonSynchronizedSingleton sync1 = SynchronizedSingleton.getInstance();SynchronizedSingleton sync2 = SynchronizedSingleton.getInstance();System.out.println(sync1 == sync2); // true// Double-checked singletonDoubleCheckedSingleton dcs1 = DoubleCheckedSingleton.getInstance();DoubleCheckedSingleton dcs2 = DoubleCheckedSingleton.getInstance();System.out.println(dcs1 == dcs2); // true// Bill Pugh singleton (recommended)BillPughSingleton bp1 = BillPughSingleton.getInstance();BillPughSingleton bp2 = BillPughSingleton.getInstance();System.out.println(bp1 == bp2); // true// Enum singleton (simplest)EnumSingleton enum1 = EnumSingleton.INSTANCE;EnumSingleton enum2 = EnumSingleton.INSTANCE;System.out.println(enum1 == enum2); // trueenum1.doSomething();// In multithreaded environmentExecutorService executor = Executors.newFixedThreadPool(10);for (int i = 0; i < 10; i++) {    executor.submit(() -> {        BillPughSingleton instance = BillPughSingleton.getInstance();        System.out.println("Thread: " + Thread.currentThread().getName() + ", Instance: " + instance);    });}executor.shutdown();

Comments

No comments yet. Be the first to comment!