Initialize-On-Demand Holder Class and Singletons

Discussions

Performance and scalability: Initialize-On-Demand Holder Class and Singletons

  1. Hi,

    I came across the Initialize-On-Demand Holder Class idiom in this article by Brian Goetz:

    http://www-128.ibm.com/developerworks/java/library/j-jtp03304/

    It seems that this would be a good way to implement a thread-safe lazy-initialized Singleton. My first question is "Does this work Ok?"

    public class S {
      private S() {}
      private static class SHolder { private static S s = new S();}
      public static S getInstance() { return SHolder.s; }
    }

    My second question is that if the above is Ok, why do I need the SHolder static inner class to ensure that the S is instantiated lazily (i.e. not until getIntance() is called)?

    Why can't I just have:

    public class S {
      private S() {}
      private static S s = new S();
      public static S getInstance() { return s; }
    }

    In my tests (which I realize might not be proving anything), S s = new S(); does not seem to get called until S.getInstance() is called by the client.

    Thanks, Jeff.
  2. Reason for inner class[ Go to top ]

    The reason you need the inner class to hold the instance is if you have other static methods you want to be able to call without creating the singleton instance.

    Static members are created when the class is first used, so calling another static method causes all static data (including the instance variable) to be initialized. By putting it in an inner class, only when the inner class is first referenced (which should only be during calls to the outer class's getInstance()) does the instance get created.

    Basically the static inner class is slightly more lazy, but you'll only notice the difference if there are other static methods on your singleton class that are called before getInstance(). In general, I'd say it's bad practice to do that (static methods other than getInstance() on a singleton), but I guess some people must do that.
  3. Thanks.
  4. Why not.

    public class S {
      private S() {}
      private static S s;
      public static S getInstance() {
         if(s == null){
            s = new S();
         }
         return s;
      }
    }
  5. Why not.public class S {  private S() {}  private static S s;  public static S getInstance() {      if(s == null){        s = new S();     }     return s;   }}

    Because, it's not thread-safe ;-)

    Best regards,
    Stefan
  6. We can also create a Singleton using Double-checked locking Pattern like this: public class S { private S() {} private static S s; public static S getInstance() { if (s == null) { synchronized(S.class) { if (s == null) s = new S(); } } } } In this case we have achieved all the goals that we were looking for. This pattern has some deficiencies (http://www.ibm.com/developerworks/java/library/j-dcl.html) but if you know your needs can be a good substitution for inner class on implementing initializing on demand for Singleton design pattern. Rgds Ali
  7. We can also create a Singleton using Double-checked locking Pattern like this:


    public class S {
    private S() {}
    private static S s;

    public static S getInstance() {
    if (s == null) {
    synchronized(S.class) {
    if (s == null) s = new S();
    }
    }
    }
    }

    In this case we have achieved all the goals that we were looking for. This pattern has some deficiencies (http://www.ibm.com/developerworks/java/library/j-dcl.html) but if you know your needs can be a good substitution for inner class on implementing initializing on demand for Singleton design pattern.
    The main deficiency of the code you have supplied is that it may not be thread-safe. For clarity, the article you reference was written in 2002. It's worth noting that this is prior to the inclusion of JSR 133 in JDK 1.5. The following articles, referred to by the OP, cover the problems with the Java Memory Model and what this means in a post JSR-133 world. http://www.ibm.com/developerworks/java/library/j-jtp02244.html http://www.ibm.com/developerworks/library/j-jtp03304/ The second link shows a truly thread-safe implementation of the double checked locking idiom, along with the (possibly) more performant (according to statement the article) implementation that is the subject of this thread as raised by the OP. Best Regards, Mathew Butler