美文网首页
Java弱引用之硬核复用机制

Java弱引用之硬核复用机制

作者: 风逝_c609 | 来源:发表于2020-04-13 15:21 被阅读0次

    弱引用不是回收了吗?怎么还复用???下面咱们来一探究竟

    1. 弱引用的常规使用

    class Resource {
        Object data;
    
        public Resource(Object data) {
            this.data = data;
        }
    
        public Object getData() {
            return data;
        }
    }
    

    写代码用弱引用测试一把

        @Test
        public void testWeakFirst() {
            Resource resource = new Resource("data can re-use");
            WeakReference<Resource> weakReference = new WeakReference(resource);
    
            System.out.println("before gc");
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference.get());
    
            System.out.println("after gc");
            resource = null;
            System.gc();
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference.get());
        }
    

    Run一把毫无悬念的结果

    before gc
    resource = team.opay.pay.Resource@484b61fc
    weakRef = team.opay.pay.Resource@484b61fc
    after gc
    resource = null
    weakRef = java.lang.ref.WeakReference@45fe3ee3
    weakRef.get = null
    
    Process finished with exit code 0
    

    常规弱引用使用测试结论

    • 弱引用包裹的对象resource返回null
    • 但是弱引用本身是(WeakReference != null)

    2. 扩展WeakReference

    2.1 简单扩展(不使用引用队列)
    class ReuseWeakReferenceI extends WeakReference<Resource> {
    
        private String key;
        private Object source;
    
        public ReuseWeakReferenceI(String key, Resource referent) {
            super(referent);
            /**
             * 这里为什么是Resource的data字段呢?
             * 因为get方法毫无悬念的为空 可以尝试引用一下起内部的变量
             */
            this.source = referent.getData();
            this.key = key;
        }
    
        public Object getSource() {
            return source;
        }
    
        public String getKey() {
            return key;
        }
    
        public void reset() {
            this.key = null;
            this.source = null;// 让gc尽快回收
            clear();
        }
    }
    

    测试代码如下

        @Test
        public void testWeakSecond() {
            Resource resource = new Resource("data can re-use");
            ReuseWeakReferenceI weakReference = new ReuseWeakReferenceI("", resource);
    
            System.out.println("before gc");
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference.get());
    
            System.out.println("after gc");
            resource = null;
            System.gc();
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference);
            System.out.println("weakRef.get = " + weakReference.get());
            System.out.println("weakRef.get = " + weakReference.getSource());
        }
    

    继续Run

    before gc
    resource = team.opay.pay.Resource@484b61fc
    weakRef = team.opay.pay.Resource@484b61fc
    after gc
    resource = null
    weakRef = team.opay.pay.ReuseWeakReferenceI@45fe3ee3
    weakRef.get = null
    weakRef.data = data can re-use
    

    2.1无引用队列测试结论
    -WeakReference引用在,其内部强引用也就在

    2.2 扩展(使用引用队列)
    class ReuseWeakReference extends WeakReference<Resource> {
    
        private String key;
        private Object source;
    
        public ReuseWeakReference(String key, Resource referent, ReferenceQueue<? super Resource> q) {
            super(referent, q);
            /**
             * 这里为什么是Resource的data字段呢?
             * 因为get方法毫无悬念的为空 可以尝试引用一下起内部的变量
             */
            this.source = referent.getData();
            this.key = key;
        }
    
        public Object getSource() {
            return source;
        }
    
        public String getKey() {
            return key;
        }
    
        public void reset() {
            this.key = null;
            this.source = null;// 让gc尽快回收
            clear();
        }
    }
    

    测试代码

    @Test
        public void testLast() {
            String key = "sourceKey";
            Resource resource = new Resource("data can re-use");
            ReferenceQueue<Resource> referenceQueue = new ReferenceQueue<>();
            ReuseWeakReference weakReference = new ReuseWeakReference(key, resource, referenceQueue);
            Map<String, ReuseWeakReference> cache = new HashMap<>();
            cache.put(key, weakReference);
    
            System.out.println("before call gc");
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference.get());
    
            resource = null;
            System.gc();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("after call gc");
            System.out.println("resource = " + resource);
            System.out.println("weakRef = " + weakReference.get());
            Reference reference;
            while ((reference = referenceQueue.poll()) != null) {
                ReuseWeakReference reuse = (ReuseWeakReference)reference;
                System.out.println("weakCacheMap size(before remove) = " + cache.size());
                cache.remove(reuse.getKey());
                System.out.println("weakCacheMap size(after remove) = " + cache.size());
                System.out.println("weakRef.queue reuse value = " + reuse.getSource());
            }
        }
    

    运行结果

    before call gc
    resource = team.opay.pay.Resource@484b61fc
    weakRef = team.opay.pay.Resource@484b61fc
    after call gc
    resource = null
    weakRef = null
    weakCacheMap size(before remove) = 1
    weakCacheMap size(after remove) = 0
    weakRef.queue ref.data (in memory) = data can re-use
    

    2.2使用引用队列扩展测试结论

    • (同2.1测试结论)

    3. Andorid Glide实践

    Glide ActiveResources之弱引用复用实践篇
    当检测到正在使用的缓存不在使用时,有如下复用处理

    • bitmap.recycle()
    • cache.put() //memoryCache
    • bitmapPool //inMutable

    相关文章

      网友评论

          本文标题:Java弱引用之硬核复用机制

          本文链接:https://www.haomeiwen.com/subject/glygmhtx.html