November 25, 2014
Hot Topics:

Threads Versus The Singleton Pattern

  • May 31, 2007
  • By Rob Lybarger
  • Send Email »
  • More Articles »

Given the recent uptake in the application of the singleton design pattern, it bears noting that certain applications of this pattern might not play nicely should they be utilized in a threaded program. That is to say, there are times when your design intent is that the "singleton" concept should be applied to a user or a transaction, and not simply to the application itself. You are rather likely to encounter this very situation if you write J2EE code because each request is typically processed from its own thread. Depending on how long some JDBC operations take for your application, you might inadvertently have a singleton helper class step on itself while dealing with two (or more) requests. Although you probably could address some of these issues with the judicious use of synchronized blocks, do not overlook the utility of the ThreadLocal class. In this article, I will demonstrate the risk of not accounting for Threads when using a singleton pattern and show how simple it is to address.

ThreadLocal Overview

The java.lang.ThreadLocal class has been present in the standard J2SE API since the 1.2 release, but it hasn't received much publicity in articles. (At least not quite as much as the singleton pattern has recently, in my opinion.) To quote from the API documentation:

"This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread."

In other words, whereas an ordinary "static" variable is shared across all instances of its class everywhere throughout the application, a "static ThreadLocal" is shared across all instance of its class only within the context of a particular thread. Because ThreadLocal itself is a type (specifically, a class) and not simply a modifier, you will initialize it an object that holds the value you otherwise would have created directly. (Make use of the primitive wrapper classes as needed.) I recommend reading the more official descriptions from the standard API, but to paraphrase, the methods are:

public Object initialValue() Functionally similar to a delayed constructor for your value object that is called the first time the get() method is called. Will return null unless you override.
public void set(Object) Setter method for the value object inside the ThreadLocal.
public Object get() Getter method for the value object inside the ThreadLocal.
public void remove() Removes the value object. If get() is called again, the initialValue() method is again triggered.

Also note that ThreadLocal itself has been "genericized." This article will show such utilization. (If you are a little weak on Java generics, this lesson, part of Sun's online Java tutorial, is a good place to start.)

Modification of a factory class that naively passes out references to a singleton to instead be thread-saavy is fairly simple. But first, you should set up a demonstration to illustrate the danger of not doing so.

Problem Demonstration

The Helper Class

First, you will define a class called Helper, whose job is to maintain some notion of state, and more specifically, the progression of changes to that state:

public class Helper {

   public static final int BEGINNING=0;
   public static final int MIDDLE=1;
   public static final int END=2;
   public static final int DONE=3;

   private int state = BEGINNING;

   public void setState(int newState) {
      state = newState;
   }

   public int getState() {
      return state;
   }

   public String toString() {
      return "Helper has state "+state;
   }
}

Usage Illustration

The usage pattern for this class is that some external section of code obtains a reference to a Helper object and, depending on the Helper's state, performs some conditional operation (and then updates the Helper's state). Note that, for the immediately following example, a singleton pattern is not yet employed. (You will get to that shortly.) This is also a fairly contrived example, and as such it sleeps (briefly) to simulate effects of long-running operations:

public class Demo1 {
   public static void main(String[] args) {
      Helper helper = new Helper();
      do {
         try {
            Thread.sleep((long)(250*Math.random()));
         } catch (InterruptedException e) {
            break;
         }
         switch (helper.getState()) {
         case Helper.BEGINNING:
            System.out.println(helper);
            System.out.println("Beginning operation finished.");
            helper.setState(Helper.MIDDLE);
            break;
         case Helper.MIDDLE:
            System.out.println(helper);
            System.out.println("Middle operation finished.");
            helper.setState(Helper.END);
            break;
         case Helper.END:
            System.out.println(helper);
            System.out.println("End operation finished.");
            helper.setState(Helper.DONE);
            break;
         }
      } while (helper.getState() != Helper.DONE);
      System.out.println("Code section finished.");
   }
}

The expectation is that the output you see on the screen is:

Helper has state 0
Beginning operation finished.
Helper has state 1
Middle operation finished.
Helper has state 2
End operation finished.
Code section finished.

... and when your code (or at least everything related to the existence and usage of the Helper object) is single-threaded, this works fine. But, for some reason (related to experience or design requirements), you drag a factory-with-singleton design into the picture.





Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel