Which Java collection should I use to implement a thread-safe cache?

后端 未结 5 1530
后悔当初
后悔当初 2021-02-20 14:58

I\'m looking to implement a simple cache without doing too much work (naturally). It seems to me that one of the standard Java collections ought to suffice, with a little extra

相关标签:
5条回答
  • 2021-02-20 15:39

    www.javolution.org has some interestig features - synchronized fast collections. In your case it worth a try as it offers also some nifty enhancements for small devices as Android ones.

    0 讨论(0)
  • 2021-02-20 15:39

    For synchronization, the Collections framework provides a synchronized map:

    Map<V,T> myMap = Collections.synchronizedMap(new HashMap<V, T>());
    

    You could then wrap this, or handle the LRU logic in a cache object.

    0 讨论(0)
  • 2021-02-20 15:43

    If you use SoftReference-based keys, the VM will bias (strongly) against recently accessed objects. However it would be quite difficult to determine the caching semantics - the only guarantee that a SoftReference gives you (over a WeakReference) is that it will be cleared before an OutOfMemoryError is thrown. It would be perfectly legal for a JVM implementation to treat them identically to WeakReferences, at which point you might end up with a cache that doesn't cache anything.

    I don't know how things work on Android, but with Sun's recent JVMs one can tweak the SoftReference behaviour with the -XX:SoftRefLRUPolicyMSPerMB command-line option, which determines the number of milliseconds that a softly-reachable object will be retained for, per MB of free memory in the heap. As you can see, this is going to be exceptionally difficult to get any predictable lifespan behaviour out of, with the added pain that this setting is global for all soft references in the VM and can't be tweaked separately for individual classes' use of SoftReferences (chances are each use will want different parameters).


    The simplest way to make an LRU cache is by extending LinkedHashMap as described here. Since you need thread-safety, the simplest way to extend this initially is to just use Collections.synchronizedMap on an instance of this custom class to ensure safe concurrent behaviour.

    Beware premature optimisation - unless you need very high throughput, the theoretically suboptimal overhead of the coarse synchronization is not likely to be an issue. And the good news - if profiling shows that you are performing too slowly due to heavy lock contention, you'll have enough information available about the runtime use of your cache that you'll be able to come up with a suitable lockless alternative (probably based on ConcurrentHashMap with some manual LRU treatment) rather than having to guess at its load profile.

    0 讨论(0)
  • 2021-02-20 15:51

    LinkedHashMap is easy to use for cache. This creates an MRU cache of size 10.

    private LinkedHashMap<File, ImageIcon> cache = new LinkedHashMap<File, ImageIcon>(10, 0.7f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<File, ImageIcon> eldest) {
            return size() > 10;
        }
    };
    

    I guess you can make a class with synchronized delegates to this LinkedHashMap. Forgive me if my understanding of synchronization is wrong.

    0 讨论(0)
  • 2021-02-20 15:54

    I like Apache Commons Collections LRUMap

    0 讨论(0)
提交回复
热议问题