3

I need a concurrent weak hash map where keys are compared with equality and not identity, as in WeakHashMap.

The answers to this similar old question:

Is there java.util.concurrent equivalent for WeakHashMap?

made it clear that there is not something like that in the JDK. However, its accepted answer wrongly suggests that Guava's CacheBuilder can do that, but CacheBuilder makes use of identity comparison, not equality comparison as I require.

The previous similar question was asked several years ago, in the meanwhile something has changed and maybe nowadays a third party library provides the implementation I need?

I could implement this using a WeakHashMap by means of storing the object to cache as the key of the map and a weak reference to it as its value, but it would not be thread safe.

Wrapping a WeakHashMap in a Collections.synchronizedMap is not really an option since the contention will be too high.

If no alternative currently exists, I am considering implementing something in the style of a ConcurrentHashMap wrapper over WeakHashMap, but is that really a good idea? Has somebody done that before?

Use case:

The reason I am asking this is because I am implementing a thread safe cache of single values (not a key-value association as in Google's Cache class) and I want these values to be garbage collected when no reference to them exists.

Community
  • 1
  • 1
Sergio
  • 8,532
  • 11
  • 52
  • 94
  • Not sure if this helps, but here ( http://grepcode.com/file/repo1.maven.org/maven2/net.maritimecloud.mms/mc-mms-client-javaee/0.2/net/maritimecloud/internal/mms/client/util/ConcurrentWeakHashSet.java ) it looks like they've implemented a "ConcurrentWeakHashSet" based on a concurrent hash map... – BretC Aug 07 '15 at 10:38
  • "and I want these *values* to be garbage collected" - `WeakHashMap` is *weak-keyed*. What you're asking for would be weak-valued. Even a synchronized WeakHashMap wouldn't work for that. – the8472 Aug 07 '15 at 10:53
  • just clarified my question. As I said, I need a cache of a single value, not a key-value pair. – Sergio Aug 07 '15 at 10:58
  • so you basically need a weak, concurrent set for the purpose of interning? how do you intend to perform get operations on it? by constructing a temporary instance and discarding it if it's already present? – the8472 Aug 07 '15 at 11:04
  • Indeed this is about interning. I do not need to construct a temporary instance myself, a client library ask me to resolve such instances and I either answer an existing one if in the cache or the instance sent if the cache did not contained it previously. – Sergio Aug 07 '15 at 11:08
  • "the contention will be too high" -- how do you know this? – kdgregory Aug 07 '15 at 11:13
  • If you choose to do this yourself, I believe you will be far better served by using `ConcurrentHashMap` with your own weak holder and reference queue, rather than trying to layer concurrency on top of `WeakHashMap`. I'm willing to bet that Doug Lea did it better than you will. – kdgregory Aug 07 '15 at 11:14
  • I am sure you will win that bet :) What do you mean about my own "weak holder"? Something like extending weak reference to allow equality comparison and storing that in the map? – Sergio Aug 07 '15 at 11:24
  • Exactly. But I'm betting that contention is far lower than you think it is. – kdgregory Aug 07 '15 at 12:21
  • what I do not like about the solution you mention is that I necessarily would need an extra thread devoted to cleaning tasks. Am I right? – Sergio Aug 07 '15 at 12:37
  • 1
    Not necessarily. I would check the queue whenever adding something to the underlying map, and clean up then. Unless you're storing millions of items in the map, leaving a few dead references around isn't going to hurt (but be sure to check for `null` on retrieval!). And if you're storing millions of items that get quickly garbage-collected, I would say that there's no need for a canonicalizing map. – kdgregory Aug 07 '15 at 15:41
  • i don't know what your underlying usecase is, but maybe `ThreadLocal>` or even `ThreadLocal>` dedicated to specific callsites may be a good alternative for GCed caches. – the8472 Aug 07 '15 at 19:00

0 Answers0