How to Use Singleton in Java etd_admin, December 1, 2024December 1, 2024 The Singleton design pattern is one of the most commonly used patterns in Java. Its purpose is to ensure that a class has only one instance while providing a global access point to it. This pattern is particularly useful in scenarios such as managing shared resources, configurations, or connections. A Singleton class ensures: Only one instance of the class exists. The instance is globally accessible. 1. Eager Initialization In this approach, the instance is created at the time of class loading. public class EagerSingleton { private static final EagerSingleton INSTANCE = new EagerSingleton(); // Private constructor to prevent instantiation private EagerSingleton() {} public static EagerSingleton getInstance() { return INSTANCE; } } Two advantages of this is that it is simple and thread-safe. It is also best suited when the instance is lightweight and always needed. 2. Lazy Initialization In this method, the instance is created only when it is requested. public class LazySingleton { private static LazySingleton instance; private LazySingleton() {} public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } } A common pitfall of this approach is that it is not thread-safe. Multiple threads can create separate instances. But one great advantage is it allows saving of resources by delaying instance creation. 3. Thread-Safe Singleton To address the thread-safety issue in lazy initialization, we use synchronized blocks. public class ThreadSafeSingleton { private static ThreadSafeSingleton instance; private ThreadSafeSingleton() {} public static synchronized ThreadSafeSingleton getInstance() { if (instance == null) { instance = new ThreadSafeSingleton(); } return instance; } } Also do note that the synchronized keyword can affect performance if called frequently. 4. Double-Checked Locking This approach minimizes the performance overhead of synchronization by checking the instance twice. public class DoubleCheckedLockingSingleton { private static volatile DoubleCheckedLockingSingleton instance; private DoubleCheckedLockingSingleton() {} public static DoubleCheckedLockingSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckedLockingSingleton.class) { if (instance == null) { instance = new DoubleCheckedLockingSingleton(); } } } return instance; } } The volatile keyword ensures the instance is visible correctly to all threads. 5. Bill Pugh Singleton This is considered one of the best approaches. It uses a static inner class for lazy loading. public class BillPughSingleton { private BillPughSingleton() {} private static class SingletonHelper { private static final BillPughSingleton INSTANCE = new BillPughSingleton(); } public static BillPughSingleton getInstance() { return SingletonHelper.INSTANCE; } } The advantages include: thread-safety, does not require synchronization and lazy initialization without extra overhead. Learning how to use Singleton in Java effectively ensures efficient and correct resource management. By choosing the right implementation and avoiding pitfalls, you can leverage its benefits without compromising the integrity of your code. When implementing, always consider the requirements of your project to decide the best variation of Singleton for your needs. Java JavaSingleton