Popular Posts

Monday, June 13, 2011

Java InterView Questions - Singleton

singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object.

the constructor is made protected (not private, because reuse and unit test could need to access the constructor).

A class designed to hold a singleton object must prevent multiple instantiations of itself from being created. This includes

  • making its constructor private
  • employing lock mechanisms to prevent an initialization routine from running simultaneously by multiple threads
  • ensuring the class is not serializable
  • ensuring the class cannot be cloned
  • preventing the class from being garbage collected if it was loaded by a custom class loader

What is Singleton? Have you used Singleton before?

Singleton is a class which has only one instance thought out the application and provides a getInstance() method to access the singleton instance.

Which classes are candidates of Singleton? Which kind of class do you make Singleton in Java?

Situations often will demand for the existence of only one object for a particular class in an Application. For example, the existence of only one Database Connection for a particular session, one object referencing the set of Global properties being shared across the various modules, etc. Such classes are candidates to be designated as Singletonclasses. The sole purpose of such a class is to ensure that only one instance of the class is created for the entire Application and that instance is shared across multiple clients.

how to make a class to behave as a Singleton class?

MyConnection.java

package tips.pattern.singleton;

public class MyConnection {

private static MyConnection connection = null;

private MyConnection(){

}

public static MyConnection getConnection(){

initObject();

return connection;

}

private static void initObject(){

if (connection == null){

connection = new MyConnection();

}

}

}

Note thatdeclaration of the private constructor which tells that no other outside classes can directly instantiate this class. The only way to get a reference to the MyConnection object is to make a call to the static method MyConnection.getConnection().

1) static object connection is not initialized in the declaration itself.

2) initObject()creates a new object for the very first time only by making a comparison check.

Will the class works well in a multi-threaded environment?

certainly not.

private static void initObject(){
    synchronized (MyConnection.class) {              
        if (connection == null){
            connection = new MyConnection(); 
        }
    }
}


What is lazy and early loading of Singleton and how will you implement it?

lazy loaded singletons using plain old synchronization, simple but effective:

What is Double-checked locking (DCL)

double-checked locking is a design pattern used to reduce the overhead of acquiring a lock by first testing the locking criterion (the "lock hint") without actually acquiring the lock. Only if the locking criterion check indicates that locking is required does the actual locking logic proceed.

class Foo {
    private Helper helper = null;
    public Helper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null) {
                    helper = new Helper();
                }
            }
        }
        return helper;
    }
 }

1. Check that the variable is initialized (without obtaining the lock). If it is initialized, return it immediately.

2. Obtain the lock.

3. Double-check whether the variable has already been initialized: if another thread acquired the lock first, it may have already done the initialization. If so, return the initialized variable.

4. Otherwise, initialize and return the variable.

J2SE 5.0, this problem has been fixed. The volatile keyword now ensures that multiple threads handle the singleton instance correctly.

static volatile Singleton instance;

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null)

instance == new Singleton();

}

} return instance;

How do you prevent for creating another instance of Singleton using clone() method?

add a clone() method of our own, and throw a CloneNotSupportedException

public Object clone()
        throws CloneNotSupportedException
  {
    throw new CloneNotSupportedException(); 
    // that'll teach 'em
  }
 

How do you prevent for creating another instance of Singleton using reflection?

Throwing exception from constructor is an option.

How do you prevent for creating another instance of Singleton during serialization?

use of readResolve() method

private Object readResolve() {
    return Instance;
  }

Initialization on demand holder idiom (IODH)

Is a lazy-loaded singleton.

Idiom can be implemented in both single-threaded/serial and concurrent environments

Example

public class Something {
        private Something() {
        }
 
        private static class LazyHolder {
                private static final Something INSTANCE = new Something();
        }
 
        public static final Something getInstance() {
                return LazyHolder.INSTANCE;
        }
}

How it works

When the class Something is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition LazyHolder within it is notinitialized until the JVM determines that LazyHolder must be executed. The static class LazyHolder is only executed when the static method getInstance is invoked on the class Something, and the first time this happens the JVM will load and initialize the LazyHolder class. The initialization of the LazyHolder class results in static variable INSTANCEbeing initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be serial, i.e., non-concurrent, no further synchronization is required in the static getInstancemethod during loading and initialization. And since the initialization phase writes the static variable INSTANCE in a serial operation, all subsequent concurrent invocations of the getInstance will return the same correctly initialized INSTANCEwithout incurring any additional synchronization overhead.

Enum-way

Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton"[9] for any Java that supports enums.

The use of an enum is very easy to implement and has no drawbacks regarding serializable objects.

Example :

public enum Singleton {
   INSTANCE;
 }

Noncompliant Code Example (Garbage Collection)

When a class is no longer reachable, it is free to be garbage collected. This behavior can be problematic when the program must maintain the singleton property throughout the entire lifetime of the program.

A static singleton becomes eligible for garbage collection when its class loader becomes eligible for garbage collection. This usually happens when a nonstandard (custom) class loader is used to load the singleton. This noncompliant code example prints different values of the hash code of the singleton object from different scopes.

  {
    ClassLoader cl1 = new MyClassLoader();
    Class class1 = cl1.loadClass(MySingleton.class.getName());
    Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
    Object singleton = classMethod.invoke(null, new Object[] { });
    System.out.println(singleton.hashCode());
  }
  ClassLoader cl1 = new MyClassLoader();
  Class class1 = cl1.loadClass(MySingleton.class.getName());
  Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
  Object singleton = classMethod.invoke(null, new Object[] { } );
  System.out.println(singleton.hashCode());

Code that is outside the scope can create another instance of the singleton class even though the requirement was to use only the original instance.

Because a singleton instance is associated with the class loader that is used to load it, it is possible to have multiple instances of the same class in the JVM. This typically happens in J2EE containers and applets. Technically, these instances are different classes that are independent of each other. Failing to protect against multiple instances of the singleton may or may not be insecure depending on the specific requirements of the program.

Compliant Solution (Prevent Garbage Collection)

This compliant solution takes into account the garbage collection issue described above. A class cannot be garbage collected until the ClassLoader object used to load it becomes eligible for garbage collection. An easier scheme to prevent the garbage collection is to ensure that there is a direct or indirect reference from a live thread to the singleton object that must be preserved.

This compliant solution demonstrates this technique. It prints a consistent hash code across all scopes. It uses the ObjectPreserver class based on [Grand 2002] and described in rule TSM02-J. Do not use background threads during class initialization.

  {
    ClassLoader cl1 = new MyClassLoader();
    Class class1 = cl1.loadClass(MySingleton.class.getName());
    Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
    Object singleton = classMethod.invoke(null, new Object[] { });
    ObjectPreserver.preserveObject(singleton); // Preserve the object
    System.out.println(singleton.hashCode());
  }
  ClassLoader cl1 = new MyClassLoader();
  Class class1 = cl1.loadClass(MySingleton.class.getName());
  Method classMethod = class1.getDeclaredMethod("getInstance", new Class[] { });
  Object singleton = ObjectPreserver.getObject();  // Retrieve the preserved object
  System.out.println(singleton.hashCode());

2 comments:

  1. Good Tutorial
    Do you have any idea on how singleton class behaves in jar file.
    if the jar file is used in project.

    ReplyDelete
  2. Found nice questions on singleton on the link below

    http://java-sample-program.blogspot.in/2012/11/singleton-interview-questions.html

    ReplyDelete