August 27, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Threads Versus The Singleton Pattern

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

The Simple Singleton Factory

Consider that you decide you do not want to instantiate multiple Helper objects—you only want one Helper object to exist. One reason for this decision is that you might have several methods in several classes that all need access to the same "state" information. That is, things are spread out farther than the simple (and admittedly contrived) do-while loop shown above. In that case, a common solution is the arrange for a factory class to provide, via a static getter method, just one instance of the Helper. Consider this simple HelperFactory class, whose job is to ensure that, when asked, it only hands out the same singular instance of a Helper class:

public class HelperFactory {
   private static Helper instance = new Helper();
   public static Helper getHelper() {
      return instance;
   }
}

The usage code above changes from Helper helper = new Helper(); to Helper helper = HelperFactory.getHelper();. Now, for that demonstrational code block, little is gained. But in a real application where, as I mentioned, your working code is spread far and wide, yet tied to the same progression of state, each interested piece of code can directly access this common, application-static Helper object via this factory getter method. (The alternative is fairly cumbersome: pass the same Helper object around in all your method calls. Enjoy the additional maintenance headaches for doing so while you're at it!) Because my assumption for this article is that you are familiar with this pattern, I won't dwell on it further.

Threaded Headaches

Now, amend your usage code somewhat to reside in the "run()" method of a Thread-derived class. Note that you also will change the println statements slightly to display the name of the thread so you can more clearly identify which thread is emitting which message. More importantly, you access a singleton Helper object via the simple factory shown above:

public class Runner extends Thread {
   public Runner(String name) {
      super(name);
   }
   public void run() {
      Helper helper = HelperFactory.getHelper();
      do {
         try {
            Thread.sleep((long)(250*Math.random()));
         } catch (InterruptedException e) {
            break;
         }
         switch (helper.getState()) {
         case Helper.BEGINNING:
            System.out.println(getName()+": "+helper);
            System.out.println(getName()+
               ": Beginning operation finished.");
            helper.setState(Helper.MIDDLE);
            break;
         case Helper.MIDDLE:
            System.out.println(getName()+": "+helper);
            System.out.println(getName()+
               ": Middle operation finished.");
            helper.setState(Helper.END);
            break;
         case Helper.END:
            System.out.println(getName()+": "+helper);
            System.out.println(getName()+
               ": End operation finished.");
            helper.setState(Helper.DONE);
            break;
         }
      } while (helper.getState() != Helper.DONE);
      System.out.println("Code section finished.");
   }
}

...and then modify the main method to create a couple Threads of this class to start them:

public class Demo2 {
   public static void main(String[] args) {
      Thread t1 = new Runner("threadA");
      t1.start();
      Thread t2 = new Runner("threadB");
      t2.start();
   }
}

Run this several times and compare the output for each run. Here's a sample when I did:

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

----------------

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

----------------

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

All output sections are different, and given the random variation of the sleep timer, this is somewhat expected. More importantly, all three are wrong—in none of them does any one thread print messages for all three helper states. (Although for different purposes you might desire the effect shown, it is wrong for the purposes of this article.) This is, at last, a visual illustration of how the two threads compete with each other for the state of the same singleton Helper object. The failure point, and the solution, lie in the factory class itself.





Page 2 of 3



Comment and Contribute

 


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

 

 


Sitemap | Contact Us

Rocket Fuel