4

在我的程序中,我有一个场景,其中多个线程将在单个 Map 上操作(放置和获取)。就像线程一样,使用在映射中放置一个键/值,同时另一个线程从映射中检索相同或不同键的键/值。现在,如果我让我的地图同步,那么这将是一个很大的性能问题,所以我决定转向 ConcurrentHashMap。在这种情况下,我有另一个复杂性,在一段时间后(我的应用程序不知道),我的应用程序中不需要很少的键/值对,所以我需要删除相同的(垃圾收集)以释放内存。尽管我的程序不知道不需要哪些键/值,但我认为使用弱引用。因此,在一段时间后,如果 key(String) 不可访问,它将自动被垃圾收集。我知道在 WeakhashMap 中执行相同操作的过程,但不知道在 ConcurrentHashMap 中执行此操作的过程。那么,谁能告诉我如何在 ConcurrentHashMap 中进行弱引用。或者还有其他方法可以实现上述场景吗?

4

1 回答 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,或什至. 然而,在当前场景中的问题是,在块内进行实际轮询,因此清理可能会减慢您的速度(但是,如果队列为空,它将不会锁定,因此它不会撤消所有的速度改进工作是正在做)。expungeStaleEntries()put()get()size()ReferenceQueue.poll()synchronizedConcurrentHashMap

于 2013-08-19T20:56:54.787 回答