Singleton pattern is a design solution where an application wants to have one and only one instance of any class, in all possible scenarios without any exceptional condition.

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.

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;
        }
        
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }

 

It 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.

public final 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;
        }
        
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }

 

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 error can be solved using double-check locking.

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;
        }
        
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }

 

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.

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() {
        }
        
        public Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    }

 

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

Next section will overcome this problem.

Using Enum

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

public enum SingletonEnum {
        INSTANCE;
        public void getInstance() {
        }
    }

 

Adding readResolve()

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.

public class SingletonDemo implements Serializable {
        private volatile static SingletonDemo INSTANCE = null;

        public static SingletonDemo getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new SingletonDemo();
            }
            return INSTANCE;
        }

        private String name = "john";

        public int getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

 

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

public class SerializationDeserializationTest {
        SingletonDemo >
        public static void main(String[] args) {
            try {
                // Serialize to a file
                ObjectOutput objOut = new ObjectOutputStream(new FileOutputStream(
                        "file.txt"));
                objOut.writeObject(ONE_INSTANCE);
                objOut.close();

                ONE_INSTANCE.setName("maxwell");

                // Serialize to a file
                ObjectInput objIn = new ObjectInputStream(new FileInputStream(
                        "file.txt"));
                SingletonDemo TWO_INSTANCE = (SingletonDemo) 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:

maxwell
john

 

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

To solve this issue, we need to include readResolve() method in our SingletonDemo 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.

public class SingletonDemo implements Serializable {
        private volatile static SingletonDemo INSTANCE = null;

        public static SingletonDemo getInstance() {
            if (INSTANCE == null) {
                INSTANCE = new SingletonDemo();
            }
            return INSTANCE;
        }
        
        protected Object readResolve() {
            return INSTANCE;
        }

        private String name = "john";

        public int getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

 

Now it will give the correct output.

 maxwell
 maxwell

 

Thanks for your reading. Please leave a comment.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit | Email Me

Leave a Reply

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