Friday, May 3, 2013

Singleton Pattern



Singleton is a class which has only one instance in whole application. This design pattern suggests that at any time there can only be one instance of a Singleton class object created by the JVM.
There are many classes in JDK which is implemented using Singleton pattern like java.lang.Runtime which provides getRuntime() method to get access of it and used to get free memory and total memory in Java.

When to use Singleton?

  • Singleton pattern used when we want to allow only a single instance of a class can be created inside our application. Using this pattern ensures that a class only have a single instance by protecting the class creation process, by setting the class constructor into private access modifier.For example, you can use it to create a connection pool. It’s not wise to create a new    connection every time a program needs to write something to a database; instead, a connection or a set of connections that are already a pool can be instantiated using the Singleton pattern.
  • Ensure that only one instance of a class is created
  • Provide a global point of access to the object
  • Allow multiple instances in the future without affecting a singleton class's clients

Different ways to create a Singleton class in Java

Lazy Initialization is a technique where one postpones the instantiation of an object until its first use. In other words the instance of a class is created when it’s required to be used for the first time. The idea behind this is to avoid unnecessary instance creation. We are going to explore each and every method to create a Singleton.

 

Singleton by synchronizing getInstance() method

To address the issue of multiple threads creating more than one instance of the singleton, make getInstance() a synchronized method.


  • Singleton has a static variable to keep its single instance.
  • You need to set the class constructor into private access modifier. Hence  you will not allow any other class to create an instance of this singleton because they have no access to the constructor.
  • getInstance() method should be called to fetch the Singleton class instance.
  • When we use our singleton in a multi-threaded application we need to make sure that instance creation process not resulting more than one instance, so we add a synchronized keywords to protect more than one thread access this method at the same time.
  • It is also advisable to override the clone() method of the java.lang.Object class and throw CloneNotSupportedException so that another instance cannot be created by cloning the singleton object.

 

 Singleton with public static final field initialized during class loading

Singleton instance is static and final variable it initialized when class is first loaded into memeory so creation of instance is inherently thread-safe.


Double check locking

In this approach the methods are not synchronized instead the instance creation code is put in a synchronized block
In the below code there are two null checks- one outside the synchronized block and one within it. The synchronized block is executed at most once and any other thread trying to get instance would have to wait until the instantiation to complete.

 

Using Enums (From Java 5 on-wards)

Creatinon of Enum instance is thread-safe by default you don't need to worry about double checked locking.
In summary, given the Serialization and thread-safety guaranteed and with couple of line of code enum Singleton pattern is best way to create Singleton in Java 5 world

Which option is better: synchronized complete getInstance() method or just critical section?
Synchronization is costly and when you apply this on whole method than call to getInstance() will be synchronized and contented. Since synchronization is only needed during initialization on singleton instance, to prevent creating another instance of Singleton,  It’s better to only synchronize critical section and not whole method.
Double checked locking is a technique to prevent creating another instance of Singleton when call to getInstance() method is made in multi-threading environment. In Double checked locking pattern as shown in below example, singleton instance is checked two times before initialization.

Double checked locking should only be used when you have requirement for lazy initialization otherwise use Enum to implement singleton or simple static final variable.

Singleton Pattern v/s Static class

  • Both Singleton pattern and static class share some similarities .Both can be used without creating object and both provide only one instance, at very high level it looks that they both serve the same purpose.
  • One key point to be remembered Singleton gives you object whereas Static class gives you methods.For an Example: java.lang.Math, which contains lots of utility methods for various maths function e.g. sqrt(). While Singleton classes are those, which has only one instance during application life cycle like java.lang.Runtime.
  • You can also choose to use static method, if you need to combine bunch of utility method together. Anything else, which requires singles access to some resource, should use Singleton design pattern.
  • Static class provides better performance than Singleton pattern, because static methods are bonded on compile time.
  •  Static classes are hard to mock and consequently hard to test than Singletons, which are pretty easy to mock and thus easy to test. It’s easier to write JUnit test for Singleton than static classes, because you can pass mock object whenever Singleton is expected, e.g. into constructor or as method arguments.
  •  Singleton classes can be lazy loaded if its an heavy object, but static class doesn't have such advantages and always eagerly loaded.
  •  If we talk about java.lang.Runtime, which is a Singleton in Java, call to getRuntime() method return different implementations based on different JVM, but guarantees only one instance per JVM, had java.lang.Runtime an static class, it’s not possible to return different implementation for different JVM.

Please find the link below to see the running example:
https://docs.google.com/file/d/0BzbinC6y3sGqdmFwOGVJY18xcTA/edit?usp=sharing

No comments:

Post a Comment