How to write a perfect Singleton implementation in java?

Pradeep Pai
4 min readJan 1, 2021

In Software Engineering design patterns holds its own fan base for making the code base clean, maintainable. Each of the design patterns are solution for some of the common software engineering problems. Out of the dozens of other design patterns, Singleton pattern is one among the popular one.

What is a Singleton pattern?

A class that is singleton can have only one object initialized from it. The single object that is created will have the information which can be used across the application.

Where can we use Singleton pattern?

Basically when there is a need of information that needs to be created upfront and cached for future use, we can use singleton.

  1. When there is a need of application to read a property file, details of which you will be using across the application. You can read the property file and store the details in a singleton object.
  2. When there is some connection information which you want to use in the software such as database info, file directory information, you can hold them in a singleton object.

What are ways to create a Singleton Class?

There are several ways to create a Singleton class and debates are around each of those implementation, since each of those implementations have their own merits and demerits. Below is the list of few common ways of creating a singleton class.

1. Eager Initialization

Lets have a look at below code.

public class EagerInitializationSingleton{private static EagerInitializationSingleton singletonInstance = new EagerInitializationSingleton();private EagerInitializationSingleton(){}public static EagerInitializationSingleton getSingletonInstance(){return singletonInstance;}}

Here you can notice that constructor is private and you can’t use new operator to create the object. Client has to use getSingletonInstance() method to get the object which will always return only one object that is singletonInstance.

This block of singleton implementation looks easy and cool, untill and unless your application is not using any resources such as database or file system. In case your singleton class is using any resources this will create memory leak problem. Hence to prevent memory leak, singleton instance has to be initialized when client calls getSingletonInstance() method.

2. Lazy Initialization

public class LazyInitializationSingleton{private static LazyInitializationSingleton singletonInstance = null;private LazyInitializationSingleton(){}public static LazyInitializationSingleton getSingletonInstance(){if(singletonInstance == null){
singletonInstance = new LazyInitializationSingleton();
}
return singletonInstance;}}

Above example shows the lazy implementation of Singleton class, which will prevent memory leaks. But this is not thread safe, if two threads tries to access getSingletonInstance() method, both the threads will end up creating its own instances since at the time of calling getSingletonInstance() method, for both the threads singletonInstance is null.

3. Making the singleton class thread safe

public class ThreadsafeSingleton{private static ThreadsafeSingleton singletonInstance = null;private ThreadsafeSingleton(){}public static synchronized ThreadsafeSingleton getSingletonInstance(){if(singletonInstance == null){
singletonInstance = new ThreadsafeSingleton();
}
return singletonInstance;}}

Above singleton implementation is thread safe, since the getSingletonInstance() method is synchronized. Here all the other threads will wait, when one of the thread is initializing the singletonInstance. But here optimization is on toss, even if the singletonInstance is already initialized, threads has to be wait in queue since the whole method is synchronized.

4. Double check locking method

public class ThreadsafeSingleton{private static ThreadsafeSingleton singletonInstance = null;private ThreadsafeSingleton(){}public static ThreadsafeSingleton getSingletonInstance(){if(singletonInstance == null){synchronized(ThreadsafeSingleton.class) {
if(singletonInstance == null){
singletonInstance = new ThreadsafeSingleton();
}
}
}return singletonInstance;}}

Double lock checking is the optimized and thread safe way of implementing singleton class. Here threads will not be blocked, if in case instance is initialized, since only a required block of code is synchronized rather than the whole method.

Above method has also got a problem. Unless and untill singletonInstance is not declared as volatile variable, above method is not perfect, since it is possible for another thread to view half initialized state of the singletonInstance.

There is no perfect implementation for a singleton class as each of these implementations got its own advantages and disadvantages. Even the singleton class with double checked locking + volatile instance is not perfect one to use, since each time state of the variable will be red from main memory instead of cache.

Disadvantages of singleton

  1. One of the major disadvantage for me to use singleton class is, it makes difficult to write a clean testable code. It interferes in unit testing. Hence some of the developers use dependency injection tools available such as Guice or Springboot to inject the instances into the required class.
  2. One or another way, it violates the single responsibility principle, since it controls its own creation and life cycle.

Conclusion

Singleton class has its own merits and demerits as there is nothing called a “Perfect Singleton Class” . But as far as there is a need of using a singleton class above are few of the ways to do it. With a proper caution, singleton class one of the best thing to use in a application.

--

--

Pradeep Pai

I'm Pradeep working as a senior software engineer at Subex. My interest lies in software engineering solving some of the complex problems.