WeakHashMap将引用放入ReferenceQueue后,如何找到_actually_条目

weakhashmap的工作原理与WeakReferenceReferenceQueue的结合非常相似-零消息有关。这是一个应该如何工作的简化示例:

public class ReferenceQueuePlayground {

    public static void main(String[] args) {
        ReferenceQueue<Referent> q = new ReferenceQueue<>();

        Referent ref = new Referent();
        WeakReference<Referent> weak = new WeakReference<>(ref,q);

        ref = null;

        // wait for GC to reclaim Referent
        while (weak.get() != null) {
            System.gc();
        }

        // this might return null,because ReferenceQueue is notified asynchronously
        // but I am assuming the happy path here 
        Reference<? extends Referent> reference = q.poll();

        // this will be false
        System.out.println(reference == null);
        // this will be true
        System.out.println(reference.get() == null);
    }

    @RequiredArgsConstructor
    @Getter
    static class Referent {

    }
}

这正是weakhashmap的工作方式-收回referent并将reference放在ReferenceQueue上时会得到通知。在随后的一些操作中,将调用expungeStaleEntries,该操作基本上将逐个抽取ReferenceQueue中的元素并对其进行操作。

我遇到的问题:如果referent现在消失了,如何对他们“起作用”?毕竟这是...HASHMap,因此要删除该元素,必须知道它是hashCode。您怎么知道hashCode即将消失的东西?

dasnan 回答:WeakHashMap将引用放入ReferenceQueue后,如何找到_actually_条目

有两种方法。第一个是线性搜索

由于指称确实消失了,并且您无法计算其上的hashCode,因此可以在整个Reference中的em> all 条目。在发布的示例中,您可以添加几行,例如:

==

这两个都将打印相同的内容,这很有意义。因此,从理论上讲,Map可以使用它得到的 WeakReference<Referent> weak = new WeakReference<>(ref,q); // <--- this System.out.println(weak); ref = null; while (weak.get() != null) { System.out.println("not yet"); System.gc(); } Reference<? extends Referent> reference = q.poll(); // <---- and this System.out.println(reference); (实际上是WeakHashMap)并遍历其内部数组,直到找到匹配项。

显然,这会很慢。

第二种方法是reference 实际上采用的方法。首次创建Entry时,它将计算WeakHashMap并将其放入本地字段:

Entry

这时它知道hashCode,因此可以计算/** * Creates new entry. */ Entry(Object key,V value,ReferenceQueue<Object> queue,int hash,Entry<K,V> next) { super(key,queue); this.value = value; this.hash = hash; this.next = next; } 。以后调用Key时:

hashCode

它已经知道expungeStaleEntries,因为它是在此之前计算出来的。它不知道 private void expungeStaleEntries() { for (Object x; (x = queue.poll()) != null; ) { synchronized (queue) { @SuppressWarnings("unchecked") Entry<K,V> e = (Entry<K,V>) x; int i = indexFor(e.hash,table.length); ,但也不需要它。

这将有助于找到该条目所在的存储桶,但要真正找到特定的条目,它只能在条目本身上使用hashCode。由于Key不见了,所以==是不可能的,但这没关系。

本文链接:https://www.f2er.com/2670020.html

大家都在问