如何在Concurrent HashMap中创建WeakReference

4
在我的程序中,有一个场景,多个线程会在同一个 Map 上进行操作(put 和 get)。例如,线程 A 在将 key/value 放入 map 中的同时,另一个线程正在检索相同或不同 key 的 key/value。现在,如果我使我的 map 同步,那么它将成为一个大问题,所以我决定转向 ConcurrentHashMap。在这种情况下,我还有另一个复杂性,就是在一定时间(对我的应用程序未知)之后,我的应用程序不需要某些 key/value 对,因此我需要删除它们(垃圾回收),以释放内存。虽然我的程序不知道哪些键/值对不需要,但我想使用弱引用来解决这个问题。因此,如果在一段时间后无法访问该 key(字符串),它将自动被垃圾回收。我知道如何在 WeakHashMap 中执行此操作,但不知道如何在 ConcurrentHashMap 中执行此操作。请问是否有人可以告诉我如何在 ConcurrentHashMap 中使用弱引用?否则是否有其他方法可以实现上述场景?

请查看此参考链接:https://dev59.com/-WUp5IYBdhLWcg3wLVOn,或许可以帮到你。 - Aliaksei Bulhak
如何使用WeakReference实例化java.util.concurrent.ConcurrentHashMap - Souvik
1个回答

3

查看 WeakHashMap 代码,似乎没有直接的方法来实现这一点,但以下形式的代码应该可以工作:(此代码尚未经过测试,但我认为它至少在正确的路径上,而且它只实现了put和get,其他操作也可以同样实现)

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);
        }
    }
}

除了上面代码的潜在错误之外,另一个注意事项是WeakHashMap通过每次调用put()、get()甚至size()刻意地调用自己的expungeStaleEntries()方法来工作。然而,在当前场景下,问题在于ReferenceQueue.poll()在synchronized块内进行实际轮询,因此清理可能会使您变慢(但如果队列为空,则不会锁定,因此它不会撤消ConcurrentHashMap正在执行的所有速度改进工作)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接