How singleton pattern works in Java

You may also like to read:

Introduction

Here in this post we will see 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 JMVs.

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

Prerequisites

Java 1.8, Eclipse Neon

Example with Source Code

There are several ways to implement the singleton pattern. The following sections will give an idea how singleton pattern is 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.jeejava.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 required first time.

package com.jeejava.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.jeejava.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.jeejava.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.

Next section will overcome this problem.

Using Enum

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

package com.jeejava.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.

package com.jeejava.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.jeejava.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.jeejava.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

Thanks for reading.

How singleton pattern works in Java

Leave a Reply

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

Scroll to top