Home | FAQ | Contact me

The Singleton pattern in Java...


...including a discussion of double-checked locking.

I've been doing singletons for a long time that way and it's time to look closer at the technology. Here's a Baeldung article that covers it.

The code here illustrates the article.

(1) DraconianSingleton:
/**
 * Traditional, double-locked singleton, created to study better
 * alternatives. See Baeldung article:
 * https://www.baeldung.com/java-singleton-double-checked-locking.
 *
 * There is a clear performance penalty in that each time we want to get
 * the instance of our singleton, we must acquire a potentially
 * unnecessary lock.
 */
public class DraconionSingleton
{
  private static DraconionSingleton instance;

  public static synchronized DraconionSingleton getInstance()
  {
    if( instance == null )
      instance = new DraconionSingleton();
    return instance;
  }

  // other methods...
}

This is not performant as pointed out in the comment in the code. The article improves upon this (old way) using this. It's the one I've been using for a long time. I added line 17 myself, however, because, without it, the compiler will not warn someone away from instantiating the class himself, i.e.:

    DclSingleton dcl = new DclSingleton();              DclSingleton has private access
(2) DclSingleton:
/**
 * This alternative to DraconionSingleton speeds things up,
 * because it starts by verifying whether we need to create the
 * object in the first place. Only in that case would we need to
 * acquire the lock.
 *
 * It is accused of being a bit verbose and slightly difficult to read.
 *
 * On the up-side, however, it works for classes whose initialization
 * entails exception-throwing which the solutions that following it do
 * not!
 */
public class DclSingleton
{
  private static volatile DclSingleton instance;

  private DclSingleton() { }

  public static DclSingleton getInstance()
  {
    if( instance == null )
    {
      synchronized( DclSingleton.class )
      {
        if( instance == null )
          instance = new DclSingleton();
      }
    }

    return instance;
  }

  // other methods; these can throw exceptions...
}

(I don't know what _Dcl_ is supposed to stand for in the article.) The comment in the code describes this as improving upon the draconian method, but being harder to read. Then, it moves on to simplify without sacrificing thread safety:

(3) EarlyInitializationSingleton:
/**
 * An easy way to achieve thread safety is to in-line object creation
 * or to use an equivalent static block taking advantage of the fact
 * that the JVM will initialize static fields and blocks one after
 * the other, see Java Language Specification (JLS) 12.4.2.
 *
 * This will not work when InitializeOnDemandSingleton() must throw an
 * exception in the performance of its duties.
 */
public class EarlyInitializationSingleton
{
  private static final EarlyInitializationSingleton instance = new EarlyInitializationSingleton();

  public static EarlyInitializationSingleton getInstance()
  {
    return instance;
  }

  // other methods, but initialization must be static and cannot throw exceptions...
}

but, this suffers from "out of the gate" initialization whether or not the object's ever going to be used, and then, this uses the same JLS understanding to create a lazier solution:

(4) InitializeOnDemandSingleton:
/**
 * This works because we know from the Java Language Specification reference
 * 12.4.2 that a class initialization occurs the first time any one of its
 * methods or fields is used, a nested static class can safely implement
 * lazy initialization.
 *
 * This will not work when InitializeOnDemandSingleton() must throw an
 * exception in the performance of its duties.
 */
public class InitializeOnDemandSingleton
{
  private static class InstanceHolder
  {
    private static final InitializeOnDemandSingleton instance = new InitializeOnDemandSingleton();
  }

  public static InitializeOnDemandSingleton getInstance()
  {
    return InstanceHolder.instance;
  }

  // other methods, but initialization must be static and cannot throw exceptions...
}

Finally, Joshua Block's enumeration-based solution is illustrated:

(5) EnumerationSingleton:
/**
 * This solution comes from Joshua Block's Effective Java book
 * and uses an enum instead of the class in the
 * previous example. As of this date, this solution is considered the
 * the most concise and safest way to implement a singleton.
 *
 * This will not work when EnumerationSingleton() must throw an
 * exception in the performance of its duties.
 */
public enum EnumerationSingleton
{
  instance

  // other methods, but initialization must be static and cannot throw exceptions...
}

I don't like Block's otherwise brilliant solution. It is extremely succinct and effective, but it's an enum, which looks funny since it's not a class. One does not expect an enum to do non-enum work. Also, ...

...if you get over the weirdness of using an enum as a class, you are then faced with its inability, just as (3) and (4), to handle exceptions.

I favor (2, above) when I need to do some initialization; I've tried the others and they work well too—even the Block solution.