Announcement Announcement Module
Collapse
No announcement yet.
Singletons and cache Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Singletons and cache

    Dear all,

    I had a cache wrapper Spring component (therefore Singleton by default) with a cache (as a ConcurrenMap) in it. I declared the cache like:

    Code:
    private static final ConcurrentMap<String, Object> cache = new ConcurrentHashMap<String, Object>();
    The reason why I declared the map as static is because I wanted the absolute certainty that no more than one cache objects would be on the heap, even in the event the Spring @Component annotation was taken off and therefore the class would become normal.

    I had a long discussion at work with our lead architect who said that since the cache is in a Singleton, I should not declare it as static and that static in Spring singletons is evil.

    Is declaring a cache static that evil? On the "Java Concurrency in Practice" book all the examples showed the cache map as a static instance variable. While I wouldn't see as appropriate static methods and attributes in a Spring component I believe it makes sense to declare it static.

    I had to correct the code to add, in addition to the @Component annotation, a @Scope("singleton") annotation. The architect said that this way I was declaring my intentions of having the component as Singleton. My answer was: isn't the Spring default to have singletons? What happened to configuration by default? He said that declaring the @Scope explicitly and declaring the map as instance variable was the Spring way of doing this.

    Is that true?

  • #2
    Singletons and cache

    I have the same question . Can someone answer to this ?

    Comment


    • #3
      It should be an instance variable. A static variable is for a CLASS constant, not an object's runtime state.

      Comment


      • #4
        Originally posted by chudak View Post
        It should be an instance variable. A static variable is for a CLASS constant, not an object's runtime state.
        Excuse me, but apart from the definition of static (e.g. related to class) and instance variable (e.g. object's runtime state), where can I read that static variables should be used only as constants?

        Comment


        • #5
          Originally posted by alzamabar View Post
          Excuse me, but apart from the definition of static (e.g. related to class) and instance variable (e.g. object's runtime state), where can I read that static variables should be used only as constants?
          Nowhere
          It is already contradicting to restrain static variables to constants.

          As of the singleton issue: To be completely accurate even a static cache is not guaranteed to exist only once if different classloaders come into play. If that is the case you have to reconsider your approach and maybe use some distributed cache (e.g. applying terracotta).
          If multiple classloaders are not an issue for you and you already wire things with spring, then using a Spring singleton instead of a static field is more consequent. The use of static in that mentioned book's concurrency examples is because it is not related to Spring.

          As of explicitly declaring the cache as singleton, while this is indeed the default: I guess this is a matter of taste. One might argue whether or not to explicitly document this intention.

          Regards,
          Andreas

          Comment


          • #6
            Originally posted by chudak View Post
            It should be an instance variable. A static variable is for a CLASS constant, not an object's runtime state.
            Originally posted by Andreas Senft View Post
            Nowhere
            It is already contradicting to restrain static variables to constants.

            As of the singleton issue: To be completely accurate even a static cache is not guaranteed to exist only once if different classloaders come into play. If that is the case you have to reconsider your approach and maybe use some distributed cache (e.g. applying terracotta).
            If multiple classloaders are not an issue for you and you already wire things with spring, then using a Spring singleton instead of a static field is more consequent. The use of static in that mentioned book's concurrency examples is because it is not related to Spring.

            As of explicitly declaring the cache as singleton, while this is indeed the default: I guess this is a matter of taste. One might argue whether or not to explicitly document this intention.

            Regards,
            Andreas
            Thank you Andreas. I got all your points, but probably I didn't explain MY one properly...Sorry. I already declare the cache manager as a Spring singleton: my question was: is it evil to declare the cache attribute *within* the cache manager as static and therefore the best approach is to declare it as instance variable?

            My point of view follows.

            - Distributed caching is not an issue here.

            - Static cache map = works with Singletons and Prototypes, e.g. if I don't want multiple instances of my cache lurking around, static does the trick. Please note that the case of prototypes is not realistic (e.g. we've never used them, so our lead architect made assumptions "what if...")

            - Instance cache map = works with Singletons, breaks my intentions (contract) with Prototypes, but my lead architect says that "if" we were to use prototypes than we would like multiple copies of my cache, but I replied that I *don't* want multiple instances of my cache lurking around.

            Comment


            • #7
              Alzambar, no need to apologize. I didn't elaborate on this part enough.
              In your case I would indeed recommend to use an instance variable for the cache. I agree with your architect here: *If* you ever declare the cache manager as prototype, then it would be counter-intuitive to still have a single cache (even if that is not an intended use case, at least now). And for the (intended) singleton case it works anyway with an instance property.

              Regards,
              Andreas

              Comment


              • #8
                This design conversation is closely mirroring the architecture need that I have.

                I need one updatable synchronized value within a apache tomcat war (web application). This value will be a bean.

                I am guessing that I will not have to worry about multiple classloaders.

                What strategy would you recommend for implementing this?

                Comment


                • #9
                  I'd go with the solutions already described here, just make it an instance variable.

                  Comment


                  • #10
                    Sorry if I am being a bit dense. But create a bean that is a singleton that has a static synchronized instance variable?

                    Comment


                    • #11
                      I guess it's useful to know a little about what you're doing here. If you only want one bean, it's going to be a singleton if you only one want person updating it make access synchronized, is there something I'm missing?

                      Comment


                      • #12
                        I am keeping track the number of processes running in an external system. We have a limit of processes that we can start and I am limiting that.

                        I will have a polling consumer that will update the number of processes running.

                        A message broker will need to have access to that information to determine if it can send a message that will start an external process.

                        I want to basically have one value in memory that can be updated.

                        BTW thanks for the help!

                        Comment


                        • #13
                          I don't think this has to be particularly complicated, all you need to do is synchronize access like you would normally.

                          Comment

                          Working...
                          X