Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Simply Singleton

Navigate the deceptively simple Singleton pattern

  • Print
  • Feedback

Page 5 of 6

Since double-checked locking is not guaranteed to work, you must synchronize the entire getInstance() method. However, another alternative is simple, fast, and thread-safe.

An alternative thread-safe singleton implementation

Example 7 lists a simple, fast, and thread-safe singleton implementation:

Example 7. A simple singleton

public class Singleton {
   public final static Singleton INSTANCE = new Singleton();
   private Singleton() {
         // Exists only to defeat instantiation.
      }
}

The preceding singleton implementation is thread-safe because static member variables created when declared are guaranteed to be created the first time they are accessed. You get a thread-safe implementation that automatically employs lazy instantiation; here's how you use it:

Singleton singleton = Singleton.INSTANCE;
      singleton.dothis();
      singleton.dothat();
      ...

Of course, like nearly everything else, the preceding singleton is a compromise; if you use that implementation, you can't change your mind and allow multiple singleton instances later on. With a more conservative singleton implementation, instances are obtained through a getInstance() method, and you can change those methods to return a unique instance or one of hundreds. You can't do the same with a public static member variable.

You can safely use Example 7's singleton implementation or Example 1's implementation with a synchronized getInstance() method. However, we must explore another issue: You must specify the singleton class at compile time, which is not very flexible. A registry of singletons will let us specify singleton classes at runtime.

Use a registry

Use a singleton registry to:

  • Specify singleton classes at runtime
  • Prevent singleton subclasses from allowing multiple instances

Example 8 lists a singleton class that maintains a registry of singletons, registered by class name:

Example 8. A singleton with a registry

import java.util.HashMap;
import org.apache.log4j.Logger;
public class Singleton {
   private static HashMap map = new HashMap();
   private static Logger logger = Logger.getRootLogger();
   protected Singleton() {
      // Exists only to thwart instantiation
   }
   public static synchronized Singleton getInstance(String classname) {
      if(classname == null) throw new IllegalArgumentException("Illegal classname");
         Singleton singleton = (Singleton)map.get(classname);
      if(singleton != null) {
         logger.info("got singleton from map: " + singleton);
         return singleton;
      }
      if(classname.equals("SingeltonSubclass_One"))
            singleton = new SingletonSubclass_One();         
         else if(classname.equals("SingeltonSubclass_Two"))
            singleton = new SingletonSubclass_Two();
      map.put(classname, singleton);
      logger.info("created singleton: " + singleton);
      return singleton;
   }
   // Assume functionality follows that's attractive to inherit
}

The preceding base class creates subclass instances and stores them in a map. But that base class is high maintenance because you must update its getInstance() method for every subclass. Luckily, we can use reflection to skirt that issue.

  • Print
  • Feedback

Resources