• java数据结构之WeakHashMap


    一、JAVA中的四种引用类型

      1、强引用(StrongReference):强引用是最为普遍的一种引用,如果对象被强引用,那么垃圾回收器无论如何都不会回收它,当内存不足时会抛出OutOfMemoryError异常。

      2、软引用(SoftReference):如果一个对象只被软引用,当内存空间足够时,垃圾回收器就不会回收它。当内存空间不足时,该对象就会被回收。

      3、弱引用(WeakReference):如果一个对象只被弱引用,触发GC时,不管内存是否足够,垃圾回收器都会将其回收。

      4、虚引用(PhantomReference):如果一个对象只有虚引用在引用它,垃圾回收器是可以在任意时候对其进行回收的,虚引用主要用来跟踪对象被垃圾回收器回收的活动。

    二、WeakHashMap源码分析

      由于WeakHashMap的源码和HashMap差不多,所以只说一些特别的地方。

      1、WeakHashMap对于键值对的引用类型为弱引用,WeakHashMap定义了一个ReferenceQueue来储存已经被回收了的键值对,当我们需要获取某个键值对的时候会先利用ReferenceQueue将WeakHashMap中已经被回收的键值对清除掉。

            /**
         * 用来存储已经被GC的entry
         */
        private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); 
    
            /**
         * 从表中删除陈旧的条目,通过和ReferenceQueue中进行对比,来进行删除
         */
        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;
                    }
                }
            }
        }

    ...

    private Entry<K,V>[] getTable() {
            expungeStaleEntries();
            return table;
        }
        
        public int size() {
            if (size == 0)
                return 0;
            expungeStaleEntries();
            return size;
        }
        
        public boolean isEmpty() {
            return size() == 0;
        }
        
        public V get(Object key) {
            Object k = maskNull(key);
            int h = hash(k);
            Entry<K,V>[] tab = getTable();
            int index = indexFor(h, tab.length);
            Entry<K,V> e = tab[index];
            while (e != null) {
                if (e.hash == h && eq(k, e.get()))
                    return e.value;
                e = e.next;
            }
            return null;
        }

      

      2、WeakHashMap的Entry类继承了WeakReference类,其构造函数中有一个参数queue用来传入父类构造函数中,ReferenceQueue用来保存被GC的Entry。

    Entry(Object key, V value, ReferenceQueue<Object> queue, int hash, Entry<K,V> next)

      3、WeakHashMap的初始化默认参数和HashMap相同,但是其hash方法以及resize方法不同。扩容的时候容量也是将容量变为原来的两倍

        final int hash(Object k) {
            int h = k.hashCode();
        
            // This function ensures that hashCodes that differ only by
            // constant multiples at each bit position have a bounded
            // number of collisions (approximately 8 at default load factor).
            h ^= (h >>> 20) ^ (h >>> 12);
            return h ^ (h >>> 7) ^ (h >>> 4);
        }
        
        /**
         * 确定entry的下标位置
         */
        private static int indexFor(int h, int length) {
            return h & (length-1);
        }
  • 相关阅读:
    redis(4)
    基于参数shared_pool_reserved_size进一步理解共享池shared pool原理
    如何诊断oracle数据库运行缓慢或hang住的问题
    freqently asked questions for oracle database server patching
    cpu 过高检查
    DB2和Oracle区别
    RMAN迁移数据库到ASM(一)创建ASM磁盘组
    Oracle 12C 块修改跟踪(Block chage tracking) 功能
    Oracle 12c RMAN备份与恢复实验
    Oracle ASM磁盘组迁移指导手册
  • 原文地址:https://www.cnblogs.com/kyleinjava/p/10863513.html
Copyright © 2020-2023  润新知