In my Program I have a scenario, where Mutiple Thread will operate (put and get) on a single Map. Like Thread a using put a key/value in the map and the same time another thread is retrieving the key/value from the map for the same or different key. Now if I make my map synchronize then it wil be a big performance issue, so I decided to move to ConcurrentHashMap. During this scenario, I have another complexity that after certain period of time(not known to my application) few of the key/value pairs are not needed in my application, so I need to remove the same(Garbage Collection) to free memory. Though my programm doesn't have the idea that which key/values are not needed I thought to use weakrefernce. So, after ceratin period of time if the key(String) is not reachable it will be automatically garbage collected. I know the process to do the same in WeakhashMap but doesn't know the process to do it in ConcurrentHashMap. So, can anyone tell me how to do a weakrefernce in ConcurrentHashMap. Or else is there any other way to achieve the above scenario?
-
[look this reference.](http://stackoverflow.com/questions/15456742/concurrenthashmap-with-weak-keys-and-identity-hash) May be it's help) – Aliaksei Bulhak Aug 19 '13 at 19:50
-
How to instantiate a java.util.concurrent.ConcurrentHashMap with WeakReference – Souvik Aug 19 '13 at 19:55
1 Answers
Looking through the WeakHashMap
code it seems that there is no straight forward way of doing this but something of this following form should work: (This code has not actually been tested but I think it is at least on the correct path, also it only implements put and get, other operations can likewise be implemented)
public class MyMap<K, V> {
private class MyKey<K> extends WeakReference<K> {
private final int hashCode;
private MyKey(K k, ReferenceQueue<K> q) {
super(k, q);
hash = k.hashCode();
}
private MyKey(K k) {
super(k);
hash = k.hashCode();
}
@Override
public int hashCode() {
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof MyKey)) {
return false;
}
K otherKey = ((MyKey<K>) o).get();
K myKey = get();
if (otherKey != null && key != null) {
return otherKey.equals(myKey);
}
return this == o;
}
}
private final Map<MyKey<K>, V> map = new ConcurrentHashMap<MyKey<K>, V>();
private final ReferenceQueue<K> queue = new ReferenceQueue<K>();
public V put(K key, V val) {
expungeStaleEntries();
return map.put(new MyKey<K>(key, queue), val);
}
public V get(K key) {
expungeStaleEntries();
return map.get(new MyKey<K>(key));
}
private void expungeStaleEntries() {
MyKey<K> key = null;
while ((key = (MyKey<K>) queue.poll()) != null) {
map.remove(key);
}
}
}
Potential incorrectness of the above code aside, another caveat is that WeakHashMap
works by calling its own expungeStaleEntries()
method every time you call things like put()
, get()
, or even size()
. The problem with this in the current scenario however is that ReferenceQueue.poll()
does the actual polling inside of a synchronized
block so cleaning up can slow you down (however it will not lock if the queue is empty so it will not undo all of the speed-improvement work ConcurrentHashMap
is doing).

- 2,068
- 1
- 19
- 23