Tuesday, June 24, 2014

Singleton pattern

Singleton pattern: Ensures a class has only one instance, and provides
a global point of access to it.
.
There are often situations where you want an object to exist once and only once during run time of an application (e.g., for preferences, logging, thread pools, caches ...). Instantiating more than one of these objects often causes incorrect program behavior, overuse of resources or inconsistent results (due to multiple copies of objects).

The classic implementation of a singleton uses a private constructor, which is called by a static method - acting as the global point of access, preventing other classes to create new instances on their own:

public class SingletonClass{
  private static SingletonClass instance;

  private SingletonClass(){
  }

  // the static instance variable will only get instantiated once
  // after that it wont be null and therefore the private constructor
  // wont be called again
  public static SingletonClass getInstance(){
    if(instance==null){
      instance = new SingletonClass();
    }
    return instance;
  }
}

Another effect of the singleton is that the instance variable is instantiated in a lazy fashion. The object will only be created when really needed (the moment getInstance() is first called). A global variable might be created when you application begins. If an object is resource intensive and an application does not always ends up using it, using a singleton might be the better choice.

Multithreading

You have to be careful though when using multiple threads. If two threads call the getInstance() method at the same time, it may result in creating two instances of the SingletonClass. To prevent this from happening you can add synchronized to the getInstance() method:

public static syncronized SingletonClass getInstance(){
  if(instance == null){
    instance = new SingletonClass(); 
  }
  return instance;
}


Synchronized forces every thread to wait its turn before it can enter the method. No two threads may enter the method at the same time. This is expensive, particularly because the only time synchronized is relevant/needed is the first time through this method (after that instance is not null anymore).

You have three options:
  1. Use syncronized if the performance of getInstance() is not critical to your application.
  2. Use an eagerly created instance rather than an lazily created one. The JVM guarantees that the instance will be created before any thread accesses the static instance variable.
    public class SingletonClass{
      private static SingletonClass instance = new SingletonClass();
    
      private SingletonClass(){
      }
    
      public static SingletonClass getInstance(){
        return instance;
      }
    }
  3. Use double-checked locking to reduce the use of syncronization in getInstance(). We first check to see if instance is created, and if not, we syncronize. This way we only synchronize the first time, when instance is still null.
    public static SingletonClass getInstance(){    
        if(instance==null){
          synchronized (Singleton.class){ 
            if(instance==null){
              instance = new SingletonClass();
            } 
          }
        }
        return instance;
    }
You have to be careful though if you use multiple classloaders. Each classloader defines its own namespace and therefore more than one version of a class can exist, resulting in more than one instance of the singleton. By specifying the classloader yourself you can solve this issue.

No comments:

Post a Comment