Singleton Class in Java: Deep Insights

What is Singleton Class in Java ?

Singleton class in Java is a design pattern that ensures a class has only one instance and provides a global point of access to that instance. This pattern is used when you want to control the instantiation of a class and ensure that there is only one instance of the class throughout the entire application.

Singleton Class in Java

How to Create Singleton Class in Java ?

We can implement Singleton Class in Java in multiple ways.

These can be grouped into two categories:

  1. Lazy
  2. Eager

Lazy ways of Creating Singleton Class in Java

This delays the creation of the object until it is asked for.There are multiple ways to implement the lazy Singleton design. Let us look into those.

1. Simple Singleton Class

Steps

(i) Create a private Constructor so that the Singleton instance can’t be created outside the Singleton class.
(ii) Create a private static Singleton variable , but don’t initialise it.
(iii) Create a public static method “getInstance” , so that Client classes can call this method to get the Singleton instance. In this method create the Singleton object if instance is null, otherwise just return the instance.Please find below the code.

public class Singleton {

    private static Singleton instance;

    private Singleton() {}

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

}

Demerits:This design will not work in multi-threaded environment.Multiple threads can simultaneously call this getInstance API, which can result in multiple object creations.

2. Using Synchronized getInstance method – Make the getInstance method synchronized.Please find below the code.


public class Singleton {

    private static Singleton instance;

    private Singleton() {}

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

}

Demerits:Performance overhead due to synchronization of the getInstance method.

3. Using Synchronized block : Use synchronized block instead of synchronizing the entire method.

public class Singleton {

    private static Singleton instance;

    private Singleton() {}

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

}

Demerits:This will still create multiple instances if one or more threads are blocked at the line number 8.

4. Double Lock Check

public class Singleton {

    private static Singleton instance;

    private Singleton() {}

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

Demerits: This design is still faulty. Let me explain it in simple terms.Each thread in java has it’s own local memory or cache. It stores all the accessible variables in it’s cache for code optimization.The sync between the local cache and main memory is done by JVM. Let’s say thread A acquires the lock and creates the instance. But  it may happen that when thread B enters the block the instance may not have constructed fully and it may get a half baked object.

5. Using volatile: When we mark the variable as volatile , we tell the JVM to never keep the variable in thread’s local cache. Each thread read and write the variable to the main memory. This helps in overcoming the demerits of double lock checking.

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

}

Eager Ways of Creating of Singleton Class in java

The instance is created when the class is loaded.

1. Simple Singleton :This should be used in case the cost of creating of object is not expensive.

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }

}

2. Using enum: Since java 5 onwards,enum has been used to implement Singleton.Enums are by default Singleton and thread-safe.Also enums are automatically Serializable.

public enum Singleton {
    INSTANCE;
}

Handling Serialization

Singleton breaks once we implement the Serializable interface. When a singleton is serialized and then deserialized more than once, there will be multiple instances of Singleton created.We can avoid the creation of multiple instances by using readResolve() method and thereby discarding newly created instance by replacing with Singleton.

Please visit Serialization for more information.

public class Singleton implements Serializable {

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

    private Object readResolve() {
        return instance;
    }

}

Applications of Singleton Class in Java

It should be used wherein we need just a single instance and a global access point to a shared resource.

  1. Logging – Single point access to logging. This Singleton class should print logs in the respective streams.
  2. Configuration Loading – Singleton Config Loader class to load config files and store it in maps at application startup.
  3. Caching – Single point access to caching functionality.
  4. Factory – Global access point to create objects based on certain conditions.
  5. Thread pool – This Singleton class helps in managing shared threads.

Verdict: Eager or Lazy way of Creating Singleton Class in Java

  1. If the cost of object creation is expensive, then go for lazy volatile implementation.
  2. If the cost of object creation is very minimal, then go for eager enum implementation.

Conclusion: Singleton Class in Java

Singleton Class in Java is a design pattern that ensures the existence of only one instance of a class throughout an application and provides a global point of access to that instance.

Singleton classes can be useful in scenarios where you need to manage a single instance of a resource-intensive object or maintain a consistent configuration throughout the application. However, it’s important to carefully consider the design choices and thread safety mechanisms to ensure the Singleton pattern works effectively in your application context.

Read More: Design Patterns in Java: For Efficient Development 2023

3 comments

  1. Like the readResolve for getting around serialization scenario, it is interesting. Thanks Gyan for the extensive coverage. This helps me to identify the multiple aspects related to creating a singleton and thus consequences the same.

  2. Readresolve for serialization scenario is interesting. Thanks Gyan for the extensive coverage around singleton. Has refreshed my understanding of the consequences of various tactics and thus consequences of creating a singleton.

Leave a Reply

Your email address will not be published. Required fields are marked *