How singleton pattern works in Java

Introduction

Here in this post we will discuss how singleton pattern works in Java. Singleton pattern is a design solution, where an application wants to have one and only one instance of a class, in all possible scenarios without any exceptional condition. The singleton instance is actually created per JVM but not across multiple JMVs.

The singleton class has a private constructor that prevents creation of instance from outside the class, i.e., the class itself controls the creation of the object. The singleton class defines a public static operation that returns a sole instance of the class.

Why do we need Singleton class?

We should use singleton class as a centralized manager to internal or external resources when we need a single point of access to certain data which would be available centrally.

The following scenarios where singleton class would be under consideration:

  • We want the static data from database would be loaded at application startup and these data could be accessed centrally by the application.
  • We want to maintain application cache, we can use singleton class as a single point to put and get cached objects.

Prerequisites

Java 1.8

Different ways of implementation

There are several ways to implement the singleton pattern. The following sections give an idea how singleton pattern can be implemented.

Eager Initialization

In this pattern an instance of a class is created much before it is actually required. Mostly it is done on system start up.

package com.roytuts.pattern.singleton;
public class EagerSingletonInitialize {
	private static volatile EagerSingletonInitialize INSTANCE = new EagerSingletonInitialize();
	// private constructor to prevent creating object by other classes
	private EagerSingletonInitialize() {
	}
	public synchronized static EagerSingletonInitialize getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new EagerSingletonInitialize();
		}
		return INSTANCE;
	}
}

The above example works fine, but has one performance drawback. The getInstance() method is synchronized and each call will require extra locking/unlocking steps which are necessary only for first time, and never there after.

Lazy Initialization

In singleton pattern, it restricts the creation of instance until the instance is required for first time.

package com.roytuts.pattern.singleton;
public class SingletonLazyInitialize {
	private static volatile SingletonLazyInitialize INSTANCE = null;
	// private constructor to prevent creating object by other classes
	private SingletonLazyInitialize() {
	}
	public static SingletonLazyInitialize getInstance() {
		if (INSTANCE == null) {
			synchronized (SingletonLazyInitialize.class) {
				INSTANCE = new SingletonLazyInitialize();
			}
		}
		return INSTANCE;
	}
}

At first request, the above method ckecks whether an instance created or not. If there is no instance then it will create an instance and will return its reference. If instance was already created, it will simply return the reference of the existing instance.

But, it has also drawbacks. Suppose there are two or more threads and all comes to create instance and execute instance==null, now all threads have identified instance variable to null, thus assume they must create an instance. They sequentially goes to synchronized block and create the instances. At the end, we have several instances in our application.

This issue can be solved using double-check locking as shown in the below source code.

In the double-check locking we first check whether the instance is null or not. If the instance is null then we create synchronized block and again we check if the instance is null or not. This way we prevent several instance creation from the singleton class.

package com.roytuts.pattern.singleton;
public class SingletonThreadSafe {
	private static volatile SingletonThreadSafe INSTANCE = null;
	// private constructor to prevent creating object by other classes
	private SingletonThreadSafe() {
	}
	public static SingletonThreadSafe getInstance() {
		if (INSTANCE == null) {
			synchronized (SingletonThreadSafe.class) {
				// Double check
				if (INSTANCE == null) {
					INSTANCE = new SingletonThreadSafe();
				}
			}
		}
		return INSTANCE;
	}
}

Static Block Initialization

Static blocks are executed during the loading of class and even before the constructor is called. This feature is also used in singleton pattern.

package com.roytuts.pattern.singleton;
public class SingletonStaticBlock {
	private static final SingletonStaticBlock INSTANCE;
	static {
		try {
			INSTANCE = new SingletonStaticBlock();
		} catch (Exception e) {
			throw new RuntimeException("Instance Error!", e);
		}
	}
	public static SingletonStaticBlock getInstance() {
		return INSTANCE;
	}
	// private constructor to prevent creating object by other classes
	private SingletonStaticBlock() {
	}
}

Above code has one drawback. One instance will be created irrespective of whether we need it or not.

In next section we will overcome this problem.

Using Enum

Enum provides implicit support for thread safety and only one instance is guaranteed.

package com.roytuts.pattern.singleton;
public enum SingletonEnum {
	INSTANCE;
	public void getInstance() {
	}
}

Serialization in Singleton Class

Even there are several ways of implementing singleton pattern but still it may arise some problems.

For example, there is an application which is distributed and frequently serializes the objects in file system. Only read those objects at later time when required. So in this case the class needs to implement Serializable interface for special operation.

So, a serializable class is required when we need an object to be converted into a byte stream so that the byte stream can be converted back into a copy of the object.

Using serialization into singleton class creates multiple copies of singleton instance. We will see in the below example how we can stop serialization to make multiple copies of singleton instance in the Singleton class.

package com.roytuts.pattern.singleton;
import java.io.Serializable;
public class SingletonSerializable implements Serializable {
	private static final long serialVersionUID = 1L;
	private volatile static SingletonSerializable INSTANCE = null;
    public static SingletonSerializable getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new SingletonSerializable();
        }
        return INSTANCE;
    }
    private String name = "Soumitra";
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Let’s serialize and de-serialize it after making some changes:

package com.roytuts.pattern.singleton;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class SerializationDeserializationTest {
	public static void main(String[] args) {
		try {
			SingletonSerializable ONE_INSTANCE = SingletonSerializable.getInstance();
			// Serialize to a file
			ObjectOutput objOut = new ObjectOutputStream(new FileOutputStream("file.txt"));
			objOut.writeObject(ONE_INSTANCE);
			objOut.close();
			ONE_INSTANCE.setName("Sushil");
			// Deserialize from a file
			ObjectInput objIn = new ObjectInputStream(new FileInputStream("file.txt"));
			SingletonSerializable TWO_INSTANCE = (SingletonSerializable) objIn.readObject();
			objIn.close();
			System.out.println(ONE_INSTANCE.getName());
			System.out.println(TWO_INSTANCE.getName());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

Output

Sushil
Soumitra

As we see both variables have different value. So it means that there are two instances of the same singleton class.

To solve this issue, i.e., to prevent creating multiple instances from the class that implements Serializable interface, we need to include readResolve() method in our SingletonSerializable class. This method will be invoked when you will de-serialize the object. Inside this method, we must return the existing instance to ensure single instance application wide.

package com.roytuts.pattern.singleton;
import java.io.Serializable;
public class SingletonSerializable implements Serializable {
	private static final long serialVersionUID = 1L;
	private volatile static SingletonSerializable INSTANCE = null;
	public static SingletonSerializable getInstance() {
		if (INSTANCE == null) {
			INSTANCE = new SingletonSerializable();
		}
		return INSTANCE;
	}
	protected Object readResolve() {
		return INSTANCE;
	}
	private String name = "Soumitra";
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

Now it will give the correct output.

Sushil
Sushil

Singleton vs Static class

We can achieve the same results (what we get from singleton class) using static class but the question is which strategy should be used when?

As a rule of thumb we should use singleton when we have to deal with object data and use static class when we need to operate on data but do not store any object specific data, e.g, java.lang.Math class. Static classes should be used more like libraries.

Thanks for reading.

Leave a Comment