The Singleton Design Pattern

                               Smart Techie

                         The singleton design pattern is one of the creational patterns. “The Singleton Design Pattern will ensure that there is only one instance of a class”. The term came from the mathematical concept of a singleton. In mathematics, a singleton, also known as a unit set,[1] is a set with exactly one element. The class diagram of the Singleton is given below.

 Singleton Design Pattern

                            The below design elements need to consider when we are developing the singleton class. The Singleton class will contain,

  • Static Member – This contains the instance of the singleton class.
  • Private Constructor – This will prevent anybody else to instantiate the Singleton class.
  • Static Public Method – This provides the global point of access to the Singleton object and returns the instance to the client calling class.

Now, we will see the implementation of the singleton design pattern.

 Singleton with lazy initialization:

The example implementation is going to use lazy initialization.

package org.smarttechie;
public class SingletonLazyInitialization {
private static SingletonLazyInitialization singletonInstance;
private SingletonLazyInitialization() {
 System.out.println("==Instance created==");
}
// Providing Global point of access
public static SingletonLazyInitialization getSingletonInstance() {
if (null == singletonInstance) {
 try
   Thread.sleep(2000);
 } catch (InterruptedException e) {
    e.printStackTrace();
 }
    singletonInstance = new SingletonLazyInitialization();
 }
  System.out.println("==Get instance called ==");
 return singletonInstance;
 }
}

The explanation is given below.

Singleton Design Pattern Lazy Initialization

We will test the above code with the client code.

package org.smarttechie;
public class SingletonLazyInitializationTest {
public static void main(String[] args) {
  SingletonLazyInitialization.getSingletonInstance();
  SingletonLazyInitialization.getSingletonInstance();
  SingletonLazyInitialization.getSingletonInstance();
  SingletonLazyInitialization.getSingletonInstance();
 }
}

The output of the code is given below.

==Instance created==
==Get instance called ==
==Get instance called ==
==Get instance called ==
==Get instance called ==

The output is telling there is only one object has been created when we call getSingletonInstance() method the first time. For the subsequent calls, the created object reference has been returned.

We will test the same SingletonLazyInitialization class with the multi-threaded environment. The thread class code is given below.

package org.smarttechie;
public class SampleThread implements Runnable {
@Override
public void run() {
  SingletonLazyInitialization.getSingletonInstance();
 }
}

We will launch multiple threads to test the SingletonLazyInitialization class. The client code is provided below.

package org.smarttechie;
public class SingletonLazyInitializationTest {
public static void main(String[] args) {
 SampleThread s1 = new SampleThread();
 SampleThread s2 = new SampleThread();
 Thread t = new Thread(s1);
 Thread u = new Thread(s2);
 t.start();
 u.start();
 }
}

The output of the above code is given below.

==Instance created==
==Instance created==
==Get instance called ==
==Get instance called ==

From the output, we can observe that the constructor called twice and two instances have been created. So, in a multi-threaded environment, the SingletonLazyInitialization won’t work.

The advantages of the above implementation are “Faster, because of lazy initialization. Works well in the single-threaded environment”.

The disadvantages of the above implementation are “It will give abrupt behavior in a multi-threaded environment. Possibly create multiple instances”.

Singleton with double check locking:

                      The singleton with lazy initialization will not assure that there is only one instance in the multi-threaded environment. To make singleton to work in a multi-threaded environment, we need to use some lock so that the subsequent threads won’t get into “getSingletonInstance()” method.

The implementation is given below.

package org.smarttechie;

public class SingletonDoubleCheckLock {

private static SingletonDoubleCheckLock singletonInstance;

private SingletonDoubleCheckLock() {
 System.out.println("==Instance created==");
 }

// Providing Global point of access
 public static SingletonDoubleCheckLock getSingletonInstance() {
  if (null == singletonInstance) {
  try {
   Thread.sleep(2000);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
   synchronized (SingletonDoubleCheckLock.class){
   if (null == singletonInstance) {
    singletonInstance = new SingletonDoubleCheckLock();
   }
  }
 }
 System.out.println("==Get instance called ==");
 return singletonInstance;
 }

}

The explanation is given below.

Singleton double checking locking

We will test the above implementation in a multi-threaded environment. The client code is given below.

package org.smarttechie;

public class SingletonDoubleCheckLockTest {

public static void main(String[] args) {
 SampleThreadDoubleCheckLock s1 = new SampleThreadDoubleCheckLock();
 SampleThreadDoubleCheckLock s2 = new SampleThreadDoubleCheckLock();
 Thread t = new Thread(s1);
 Thread u = new Thread(s2);
 t.start();
 u.start();
 }
}

The output is given below.

==Instance created==
==Get instance called ==
==Get instance called ==

From the above output, we can conclude that double check lock ensures that, at any point, the only a single instance will get created.

Singleton with early initialization:

This is the third way of implementing a singleton. The code is given below.

package org.smarttechie;

public class SingletonEarlyInitialization {

private static SingletonEarlyInitialization singletonInstance = new SingletonEarlyInitialization();

private SingletonEarlyInitialization() {
 System.out.println("==Instance created==");
 }

// Providing Global point of access
 public static SingletonEarlyInitialization getSingletonInstance() {
 System.out.println("==Get instance called ==");
 return singletonInstance;
 }

}

The explanation is given below.

Singleton early initialization

In the above code, the static variable gets initialized during the class loading. The instance is created before accessing by threads. That ensures that, in a multi-threaded environment, there is only a single instance is available. The example code used in this article is available here.

Happy learning !!!

Advertisement

Siva Janapati is an Architect with experience in building Cloud Native Microservices architectures, Reactive Systems, Large scale distributed systems, and Serverless Systems. Siva has hands-on in architecture, design, and implementation of scalable systems using Cloud, Java, Go lang, Apache Kafka, Apache Solr, Spring, Spring Boot, Lightbend reactive tech stack, APIGEE edge & on-premise and other open-source, proprietary technologies. Expertise working with and building RESTful, GraphQL APIs. He has successfully delivered multiple applications in retail, telco, and financial services domains. He manages the GitHub(https://github.com/2013techsmarts) where he put the source code of his work related to his blog posts.

Tagged with:
Posted in Creational Patterns
3 comments on “The Singleton Design Pattern
  1. Anonymous says:

    Truly informative.

    Cheers!

  2. Siva says:

    Singleton design pattern explained very clearly with examples. Thanks for that and would love to see more topics from you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Dzone.com
DZone

DZone MVB

Java Code Geeks
Java Code Geeks
OpenSourceForYou
%d bloggers like this: