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 2 of 6

Second, notice that ClassicSingleton implements a protected constructor so clients cannot instantiate ClassicSingleton instances; however, you may be surprised to discover that the following code is perfectly legal:

public class SingletonInstantiator { 
  public SingletonInstantiator() { 
   ClassicSingleton instance = ClassicSingleton.getInstance();
ClassicSingleton anotherInstance =
new ClassicSingleton();
       ... 
  } 
}

How can the class in the preceding code fragment—which does not extend ClassicSingleton—create a ClassicSingleton instance if the ClassicSingleton constructor is protected? The answer is that protected constructors can be called by subclasses and by other classes in the same package. Because ClassicSingleton and SingletonInstantiator are in the same package (the default package), SingletonInstantiator() methods can create ClassicSingleton instances. This dilemma has two solutions: You can make the ClassicSingleton constructor private so that only ClassicSingleton() methods call it; however, that means ClassicSingleton cannot be subclassed. Sometimes, that is a desirable solution; if so, it's a good idea to declare your singleton class final, which makes that intention explicit and allows the compiler to apply performance optimizations. The other solution is to put your singleton class in an explicit package, so classes in other packages (including the default package) cannot instantiate singleton instances.

A third interesting point about ClassicSingleton: it's possible to have multiple singleton instances if classes loaded by different classloaders access a singleton. That scenario is not so far-fetched; for example, some servlet containers use distinct classloaders for each servlet, so if two servlets access a singleton, they will each have their own instance.

Fourth, if ClassicSingleton implements the java.io.Serializable interface, the class's instances can be serialized and deserialized. However, if you serialize a singleton object and subsequently deserialize that object more than once, you will have multiple singleton instances.

Finally, and perhaps most important, Example 1's ClassicSingleton class is not thread-safe. If two threads—we'll call them Thread 1 and Thread 2—call ClassicSingleton.getInstance() at the same time, two ClassicSingleton instances can be created if Thread 1 is preempted just after it enters the if block and control is subsequently given to Thread 2.

As you can see from the preceding discussion, although the Singleton pattern is one of the simplest design patterns, implementing it in Java is anything but simple. The rest of this article addresses Java-specific considerations for the Singleton pattern, but first let's take a short detour to see how you can test your singleton classes.

Test singletons

Throughout the rest of this article, I use JUnit in concert with log4j to test singleton classes. If you are not familiar with JUnit or log4j, see Resources.

Example 2 lists a JUnit test case that tests Example 1's singleton:

  • Print
  • Feedback

Resources