About NewTechnoBuzz
Advertise
Contact Us

Friday, July 25, 2014

Singleton Design Pattern in Java

Singleton is a part of Gang of Four design pattern and it is categorized under creational design patterns. From the definition, it seems to be a very simple design pattern but when it comes to implementation, it comes with a lot of implementation concerns. The implementation of Singleton pattern has always been a controversial topic among developers.

In this tutorial, we will learn about Singleton design pattern principles, different ways to implement Singleton and take a deeper look into its usage. We'll cover following things in this tutorial:
  • How to implement Singleton Pattern in Java
  • How to eagerly initialized Singleton Pattern
  • Static block initialization
  • How to lazy initialized Singleton Pattern
  • How to create Thread Safe Singleton
  • Bill Pugh strategy to implement Singleton Pattern
  • Enum implementation of Singleton Pattern
  • Serialization of Singleton

What is Singleton Pattern

It ensures that there is only one instance of a class is created in the Java Virtual Machine (JVM). It is used to provide global point of access to the object. In terms of practical use Singleton patterns are used in logging, caches, thread pools, configuration settings, device driver objects.
Singleton design pattern is also used in other design patterns like Abstract Factory, Builder, Prototype, Facade etc.

How to implement Singleton Pattern in Java

To implement Singleton pattern, the following are common concepts among different approaches.
  • Private constructor to restrict instantiation of the class from other classes.
  • Private static variable of the same class that is the only instance of the class.
  • Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.


Eager Initialization of Singleton Pattern

In eager initialization, the instance of class is created much before it is actually required (i.e. at the time of class loading). This is the easiest method to create singleton class but the drawback of this approach is that the singleton instance is created irrespective of whether any other class actually asked for its instance or not.

Below is the implementation of eager initialization of singleton class.

package com.gsms.console.singleton.test;
 
public class EagerSingletonInitialization {
     
    private static final EagerSingletonInitialization instance = new EagerSingletonInitialization();
     
    //private constructor to create any object
    private EagerSingletonInitialization(){}
 
    public static EagerSingletonInitialization getInstance(){
        return instance;
    }
}

Above method works fine, but has one drawback. Instance is created irrespective of it is required in runtime or not. If your singleton class is not using a lot of resources, you can use this approach. But in most of the cases, Singleton classes are created for resources like File System, Database connections etc. and we should avoid the instantiation until getInstance() method is called.

Static Block Initialization

Static block initialization implementation is similar to eager initialization. If you have little idea about class loading, then you know the fact that static blocks are executed during the class loading and called even before the constructor is called.

Below is the static block initialization of singleton class.

package com.gsms.console.singleton.test;

public class StaticBlockSingletonInitialization {
    private static final StaticBlockSingletonInitialization instance;
 
    static {
        try {
            instance = new StaticBlockSingletonInitialization();
        } catch (Exception ex) {
            throw new RuntimeException("Exception : ", ex);
        }
    }
 
    public static StaticBlockSingletonInitialization getInstance() {
        return instance;
    }
 
    private StaticBlockSingletonInitialization() {
    }
}

This approach has also same drawback like eager initialization as it also creates the instance even before it’s being used and that is not the best practice to use.


Lazy Initialization of Singleton Pattern

In computer programming, lazy initialization is the tactic of delaying the creation of an object, or some other expensive process until the first time it is needed. Lazy initialization method creates the singleton object when it is requested first time.

Below is the implementation of lazy initialization of creating Singleton class.

package com.gsms.console.singleton.test;

public class LazySingletonInitialization {
 
    private static LazySingletonInitialization instance;
     
    private LazySingletonInitialization(){}
     
    public static LazySingletonInitialization getInstance(){
        if (instance == null){
            instance = new LazySingletonInitialization();
        }
        return instance;
    }
}

The above implementation works fine in case of single threaded environment but in multi-threaded environment, this method has drawbacks.
Lets see how. Suppose there are two threads T1 and T2. Both comes to create instance and execute "instance == null", and both threads have identified instance variable to null so they create an instance. They sequentially goes to synchronized block and create the instances.

At the end, we have two instances in our application. It will destroy the singleton pattern and both threads will get the different instances of singleton class. In next section, we will see a thread-safe singleton class.

Thread Safe Singleton

The easier way to create a thread-safe singleton class is to make the global access method synchronized, so that only one thread can execute this method at a time.

Below is the implementation of thread-safe Singleton class;

package com.gsms.console.singleton.test;

public class ThreadSafeSingletonClass {
 
    private static ThreadSafeSingletonClass instance;
     
    private ThreadSafeSingletonClass(){}
     
    public static synchronized ThreadSafeSingletonClass getInstance(){
        if (instance == null){
            instance = new ThreadSafeSingletonClass();
        }
        return instance;
    }   
}

Above implementation works fine and provides thread-safety but it reduces the performance because of cost associated with the synchronized method.



To avoid this extra overhead every time, double checked locking principle is used. This principle tells us to recheck the instance variable again to ensure that only one instance of singleton class is created.

Below is the implementation of double check locking:

package com.gsms.console.singleton.test;

public class DoubleCheckSingletonClass {
    private static volatile DoubleCheckSingletonClass instance = null;
 
    private DoubleCheckSingletonClass() {
    }
 
    public static DoubleCheckSingletonClass getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckSingletonClass.class) {
                // Double check
                if (instance == null) {
                    instance = new DoubleCheckSingletonClass();
                }
            }
        }
        return instance;
    }
}

Bill Pugh Strategy

Bill pugh was main force behind java memory model changes. His principle “Initialization-on-demand holder idiom” also uses static block but in different way. It suggest to use static inner class.

In multi-threaded, when many threads try to get the instance of the Singleton class simultaneously then there are a lots of problems occur. So, Bill Pugh came up with a different approach to create the Singleton class using a inner static helper class.

Below is the Bill Pugh implementation of Singleton class:

package com.gsms.console.singleton.test;

public class BillPughSingletonClass {
 
    private BillPughSingletonClass(){}
     
    private static class SingletonHelperClass {
        private static final BillPughSingletonClass instance = new BillPughSingletonClass();
    }
     
    public static BillPughSingletonClass getInstance(){
        return SingletonHelperClass.instance;
    }
}

The private inner static class contains the instance of the singleton class. When the singleton class is loaded, SingletonHelperClass class is not loaded into memory and only when someone calls the getInstance() method, this class gets loaded and creates the Singleton class instance.


Serialization of Singleton

Lets say your application is distributed and it frequently serialize the objects in file system, only to read them later when required. Please note that, de-serialization always creates a new instance. Lets understand using an example:

package com.gsms.console.singleton.test;

public class SingletonClass implements Serializable {
    private volatile static SingletonClass instance = null;
 
    public static SingletonClass getInstance() {
        if (instance == null) {
            instance = new SingletonClass ();
        }
        return instance;
    }
 
    private int i = 20;
 
    public int getI() {
        return i;
    }
 
    public void setI(int i) {
        this.i = i;
    }
}

Lets serialize the class and then de-serialize it after making some changes:

package com.gsms.console.singleton.test;

public class SingletonClass implements Serializable {
    private volatile static SingletonClass instance = null;
 
    public static SingletonClass getInstance() {
        if (instance == null) {
            instance = new SingletonClass ();
        }
        return instance;
    }
 
    private int i = 20;
 
    public int getI() {
        return i;
    }
 
    public void setI(int i) {
        this.i = i;
    }
}

public class SerializationSingletonTest {
    static SingletonClass instance = SingletonClass .getInstance();
 
    public static void main(String[] args) {
        try {
            // Serialize to a file
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                    "filename.ser"));
            out.writeObject(instance);
            out.close();
 
            instance.setI(30);
 
            // Serialize to a file
            ObjectInput in = new ObjectInputStream(new FileInputStream(
                    "filename.ser"));
            SingletonClass instance2 = (SingletonClass ) in.readObject();
            in.close();
 
            System.out.println(instance.getI());
            System.out.println(instance2.getI());
 
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
 
Output:
30
20

Unfortunately, both variables have different value of variable "i". To solve this issue, we need to include readResolve() method in our SingletonClass 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.gsms.console.singleton.test;

public class SingletonClass implements Serializable {
    private volatile static SingletonClass instance = null;
 
    public static SingletonClass getInstance() {
        if (instance == null) {
            instance = new SingletonClass ();
        }
        return instance;
    }
 
    protected Object readResolve() {
        return instance;
    }

    private int i = 20;
 
    public int getI() {
        return i;
    }
 
    public void setI(int i) {
        this.i = i;
    }
}

Now when you execute the class SerializationSingletonTest, it will give following output.

Output:
30
30

Adding serial version id

This is required when your class structure can change after you serialize the instance and before de-serialize it. The changed structure of class will cause JVM to give exception while de-serializing process.

java.io.InvalidClassException: com.gsms.console.singleton.test.SingletonClass; local class incompatible: stream classdesc serialVersionUID = 528374520363821, local class serialVersionUID = 792417264378164
at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.gsms.console.singleton.test.SerializationSingletonTest.main(SerializationSingletonTest.java:23)

This problem can be solved by adding a unique serial version id to class. It will prevent the compiler to throw the exception by telling that both classes are same, and will load the available instance variables only.


Enum implementation of Singleton Pattern

This type of implementation recommend the use of enum. Enum, provide implicit support for thread safety and only one instance is guaranteed. This is also a good way to have singleton with minimum effort.

package com.gsms.console.singleton.test;
 
public enum EnumSingleton {
 
    INSTANCE;
     
    public static void doSomething(){
        //do something
    }
}

I hope this article helps you to understand fine details of Singleton design pattern. Let me know your thoughts, comments, suggestions and feedbacks.


0 comments