zoukankan      html  css  js  c++  java
  • 你了解WeakHashMap吗

    你了解WeakHashMap吗

    WeakHashMap正是由于使用的是弱引用,因此它的对象可能被随时回收。在缓存场景下,由于内存是有限的,不能缓存所有对象,因此就需要一定的删除机制,淘汰掉一些对象。允许null键。

    下面我们就来看看,WeakHashMap是如何实现这些功能。

    Entry作用

    //继承WeakReference
     private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
            V value;
            int hash;
            Entry<K,V> next;
    
            /**
             * Creates new entry.
             */
            Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next) {
                //这个super很关键,调用WeakReference的构造方法,使用key做referent
                super(key, queue);
                this.value = value;
                this.hash  = hash;
                this.next  = next;
            }
    
            @SuppressWarnings("unchecked")
            public K getKey() {
                return (K) WeakHashMap.unmaskNull(get());
            }
    
           //....其他省略
        }
    
    

    和HashMap一样,WeakHashMap也是用一个Entry实体来构造里面所有的元素的,但是这个Entry却和HashMap的不同,他是弱引用。就是每当进行一次gc,你这个对象就会被清除,当然如果这个对象还存在着软引用或者强引用,就可能不会被清除。

    ReferenceQueue 作用

        /**
         * Reference queue for cleared WeakEntries
         * 被清理的WeakEntries队列
         */
        private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
    

    queue是用来存放那些,被jvm清除的entry的引用,因为WeakHashMap使用的是弱引用,所以一旦gc,就会有key键被清除,所以会把entry加入到queue中。在WeakHashMap中加入queue的目的,就是为expungeStaleEntries所用。

    expungeStaleEntries方法作用

    
        /**
         * Returns the table after first expunging stale entries.
         */
        private Entry<K,V>[] getTable() {
            expungeStaleEntries();
            return table;
        }
    
         /**
          * Expunges stale entries from the table.
          * 清理掉被GC的key对应Entries
          */
        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);
    
                    Entry<K,V> prev = table[i];
                    Entry<K,V> p = prev;
                    while (p != null) {
                        Entry<K,V> next = p.next;
                        if (p == e) {
                            if (prev == e)
                                table[i] = next;
                            else
                                prev.next = next;
                            // Must not null out e.next;
                            // stale entries may be in use by a HashIterator
                            e.value = null; // Help GC 
                            size--;
                            break;
                        }
                        prev = p;
                        p = next;
                    }
                }
            }
        }
    

    实际上value的回收与key相比是有延迟的。key会被gc,而value,则是通过expungeStaleEntries赋值为null。

  • 相关阅读:
    golang gc
    set password to qcow2
    golang reflect struct
    Mac 自启动管理
    shell exec
    shell 管道 与 mkfifo
    shell 读取文件
    shell 函数
    shell read 命令
    ubuntu 快速安装和设置 mysql
  • 原文地址:https://www.cnblogs.com/dalianpai/p/14141695.html
Copyright © 2011-2022 走看看