If the construction of the singleton object is expensive, then you may consider using SoftReference instead of WeakReference.

解决方案 »

  1.   

    actually, in Java, a static variable is initialized only when the class is first accessed, right? so the following definition should be fine, by the way, you might need to make the constructor to be non-public, :-)class Singleton implements I{
    private Singleton (){}
    static final Singleton _inst=new Singleton();
    static I getInstance(){return _inst;}
    //other stuffs
    }
      

  2.   

    Well. it should be when the class is loaded.
    And, when you load a class with a method like
    void f(Singleton s){......}
    it'll load class Singleton. even if you never call Singleton.getInstance(), I believe that static variable will still be initialized.
      

  3.   

    But anyway, my point is:
    class Singleton implements I{
    private Singleton (){}
    static final Singleton _inst=new Singleton();
    static I getInstance(){return _inst;}
    //other stuffs
    }is preferable in most of the cases.
    don't always "if(_inst==null)......" because you see this on some book.
      

  4.   

    hmm, Mr. ajoo is very free :)for static initializing, there's a ordering problem, as c++ didnt say which get inited first if not in the same compilation unit. a problem indead.
    if considering concurrency, it's even worse. but there's a very effecient way called double checking idiom. you can take a look at the Singleton template for it's implementation. search ACE (The ADAPTIVE Communication Environment) in google to find the url.
      

  5.   

    Mmm? where did you get it? I thought nobody could see it because it's way after the 300 posts. 
    Thank you for up it. :)But anyway, this is not for C++. And of course you have to write your singleton as order-independent. That's not an issue in many cases.
      

  6.   

    of course ordering doesnt matter most of time. but dynamic crated one do has some advantage like runtime configuration. and much easier to make it 100% thread safe and effecient(no lock needed for accessing) if the system doesnt. the double checked optimization works for java also.
      

  7.   

    the good thing about singleton is that, the impl is transparent to the user.
    So if you don't need the lazy initialization, just keep it simple. Later, if you do need it because of the runtime configuration or any other thing, just change it.btw, thread safety/performance is one drawback of the lazy init approach, not an advantage.
    :)
      

  8.   

    also, abc, give a link bah.
    I searched and found the web site, but did not find what you were talking about.
      

  9.   

    if i don't remember wronglyif(singleton_instance==null)
    {
        lock();
        if(singleton_instance==null)
        {
             create singleton;
         }
    }
    else
    {
        return singleton_instance;
    }
    the first check only failed if singleton_instance never created. after that, you never need to lock.
      

  10.   

    I see what you mean.
    first of all, this approach makes the code even more complex.secondly, you'll still have to call if(instance==null) each time.third, this double check does not work if we use the WeakReference or SoftReference.And, the static initialized approach just does not have concurrency problem at all.
      

  11.   

    true, static initializing is ok most of the time, this just to say concurrency is not a problem for dynamicly created singleton object. BTW you can read the paper at http://www.cs.wustl.edu/~schmidt/PDF/DC-Locking.pdf  .
    http://www.cs.wustl.edu/~schmidt/ACE-papers.html for a general view of ACE.
      

  12.   

    Sorry. I'm wrong.
    The double check can also work for WeakReference and SoftReference.
    The only thing is it could be quite complex.But anyway, it's a very good idea when we do need both lazy init and thread-safety!
      

  13.   

    i have seen these codes in a paper.
    mm, talking about design patterns, but it's purpose is compare with c++.
    i think both ok if we don't care about the memory.
    but my prefer the complex codes.^_^
      

  14.   

    i have seen these codes in a paper.
    mm, talking about design patterns, but it's purpose is compare with c++.
    i think both ok if we don't care about the memory.
    but my prefer the complex codes.^_^
      

  15.   

    but when the space used by your "if(...)lock()if(...)....." is more than the memory used by the singleton object, what do you use?and, the complex code at least needs a "if(...)" everytime, slower.
      

  16.   

    at first, the code of above is wrong.
    code like that:
    public static Singleton getInstance() {
        /* in a non-thread-safe version of a Singleton   */
        /* the following line could be executed, and the */ 
        /* thread could be immediately swapped out */
        if (instance_ == null) {
          synchronized(this) {
            if (instance_ == null) {
               instance_ = new Singleton();
            }
          }
        }
        return instance_;
    }in my mind, i think it's work fine.hehe, but i have seen an article:
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.htmltake a look at it. maybe it's true.
      

  17.   

    mm, first, the singleton code is like that:package com.jgk.patterns.singleton;
    public class JGKSingleton {
      /* Here is the instance of the Singleton */
      private static JGKSingleton instance_;
      /* Need the following object to synchronize */
      /* a block */
      private static Object syncObject_;
      /* Prevent direct access to the constructor
      private JGKSingleton() {
        super();
      }
      public static JGKSingleton getInstance() {
        /* in a non-thread-safe version of a Singleton   */
        /* the following line could be executed, and the */ 
        /* thread could be immediately swapped out */
        if (instance_ == null) {
          synchronized(syncObject_) {
            if (instance_ == null) {
               instance_ = new JGKSingleton();
            }
          }
        }
        return instance_;
      }
    }in my mind, it's work fine.
    hehe, but i suspect it since i saw this article:
    http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.htmlmaybe it's true.
    i'll check it.
      

  18.   

    i think there is a good article:
    http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.htmllet's read it.^_^
      

  19.   

    Shocked!
    thought the double check works!anyway, it proves my claim: never bother complex code if not necessary.
    Thank you yakuu! It has been extremely helpful! Otherwise, I might use the double check in my future projects.
    :)
      

  20.   

    didnt know there's such a nasty problem in java's design.
    anyone knows if the memory model fixed?
    If not, then java on mp machines are broken. with immutable can be changed, your program are bond to break.
      

  21.   

    the old code:public class JGKSingleton {
      private static JGKSingleton instance_;
      private static Object syncObject_;
      public static JGKSingleton getInstance() {
        if (instance_ == null) {
          synchronized(syncObject_) {
            if (instance_ == null) {
               instance_ = new JGKSingleton();
            }
          }
        }
        return instance_;
      }
    }the new code:public class JGKSingleton {
      private static volatile JGKSingleton instance_;
      private static Object syncObject_;
      public static JGKSingleton getInstance() {
        if (instance_ == null) {
          synchronized(syncObject_) {
            if (instance_ == null) {
               instance_ = new JGKSingleton();
            }
          }
        }
        return instance_;
      }
    }
      

  22.   

    the difference is keyword:volatile ^_^
      

  23.   

    it works only in the new proposal of "volatile" semantics.
    Now, volatile does not help at all.
    But, don't think many Java code is "bound to" break.
      

  24.   

    the volatile keyword in Java is certainly not worthless or taboo. In fact, it is sometimes crucial that you do use it.Alas, the only truly useful answer is "don't use it". At least, don't rely on it for anything... 
    Basically, the language and VM specifications don't really make it clear/precise/etc. what should/shouldn't really be done in the presence of volatile and so many implementations of the JVM don't do anything if volatile is specified. Note that there are some folks actively working to solve this in time for the next release.so, we still rely upon the double check code.
      

  25.   

    the worest thing is , it breaks and you dont know. the error may happen once in 10 days or produce a result 1% larger than the original. those errors are very very hard to discover. i have heard that a bank emploree put all the interest below 1 cent to his own account when develope the system and got several handred thousand in 2 years and no auditing found it. how much checking normal program can enjoy?
      

  26.   

    concurrent programming IS tricky by itself.
    The problem with double check was not ever promised by the jls that it will work. 
    So, if any program using double check failed, it's the code's bug,(at most you can blame the jls is not clear or not good) just as many other bugs in concurrent code. They are normally hard to find in nature.
    and how many programs are using double check? don't think it's quite useful in real. As the article said, "static init" is neat and good enough.
    "volatile" may be used to fix the problem in double check in the future. But before the new jls is made and all the current impl supports that, we as programmers should just wisely avoid double check.Again, strongly recommend using "static init". Easy! most efficient! robust!
      

  27.   

    how to use it depend on yourself .both ok. i think.^_^
      

  28.   

    at least the object size has to be big enough (not just 10 bytes, 20 bytes) to justify the runtime overhead and code complexity of lazy init or double check.
      

  29.   

    alas, yes, make sure the object is big enough. mm...but how big? ^_^
      

  30.   

    no, jls didnt say that way, for example, if you have a global varible x , which is used to flag certain condition or holding something, then currently, your only hope is x is no bigger than 32 bits. because volatile doesnt work properly. BTW, immutable string can be changed make the whole immutable a joke.
      

  31.   

    he he. imutable only when you do it immutably.for example, msg = new String(...);see? msg's still mutable.and the problem is because of the mutable assignment.
      

  32.   

    ok, our discussion should be over.
    continued topic is far off.
    but can we talk about the design patterns.
    i can use 200 each topic.^_^
      

  33.   

    ok. thank you for the link!
    design patterns can easily go too abstract and phylosophical.