How Singleton Design Pattern Works in Java

Introduction

Here in this post I 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 you need Singleton class?

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

The following scenarios where singleton class would be under consideration:

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

Prerequisites

Java 1.8

Singleton Class Implementation

There are several ways to implement the singleton design pattern in Java. The following sections give you an idea how to create singleton class in Java language.

Eager Initialization

In this pattern an instance of a singleton 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 required there after.

Lazy Initialization

In lazy initialization, a singleton class in Java restricts the creation of instance until the instance is required for the 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 has already been 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 come 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 instances. In the end, you have several instances in your application.

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

In the double-check locking you first check whether the instance is null or not. If the instance is null then you need to create synchronized block and again you need to check if the instance is null or not. This way you can 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 you need it or not.

In next section you 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 you 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. You will see in the below example how you 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 you 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 creation of multiple instances from the class that implements Serializable interface, you need to include readResolve() method in our SingletonSerializable class. This method will be invoked when you will de-serialize the object. Inside this method, you 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

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

As a rule of thumb you should use singleton when you have to deal with object data and use static class when you 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.

Source Code

Download

Leave a Reply

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