利用ReferenceQueue实现自动清理的cache

理解StrongReference,SoftReference, WeakReference的区别(http://san-yun.iteye.com/blog/1683558)文中解释了各种Reference。 Reference都有构造函数可以传入ReferenceQueue来监听GC对referent的处理,构造函数如下:
Reference(T referent, ReferenceQueue<? super T> queue) {
	this.referent = referent;
	this.queue = (queue == null) ? ReferenceQueue.NULL : queue;
    }


下面是一段测试代码:
	public class A {

	}

		ReferenceQueue queue = new ReferenceQueue();
		WeakReference ref = new WeakReference(new A(), queue);
		Assert.assertNotNull(ref.get());

		Object obj = null;
		obj = queue.poll();
		Assert.assertNull(obj);

		System.gc();

		Assert.assertNull(ref.get());
		obj = queue.poll();
		Assert.assertNotNull(obj);


分析,在GC运行时,检测到new A()生成的对象只有一个WeakReference引用着,所以决定回收它,首先clear WeakReference的referent,然后referent的状态为finalizable,同时或者一段时间后把WeakReference放入监听的ReferenceQueue中。

注意有时候最后的Assert.assertNotNull(obj);有时会失败,因为还没有来的及把WeakReference放入监听的ReferenceQueue中。


下面是一个可自动回收的map实现:

import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class WeakIdentityMap {

	private transient ReferenceQueue<Object> idKeys = new ReferenceQueue<Object>();

	private Map<WeakIdKey, Object> objHashcodeToPyId = new HashMap<WeakIdKey, Object>();

	@SuppressWarnings("element-type-mismatch")
	private void cleanup() {
		Object k;
		while ((k = idKeys.poll()) != null) {
			System.out.println("cleanup");
			objHashcodeToPyId.remove(k);
		}
	}

	private class WeakIdKey extends WeakReference<Object> {
		private final int hashcode;

		WeakIdKey(Object obj) {
			super(obj, idKeys);
			hashcode = System.identityHashCode(obj);
		}

		@Override
		public int hashCode() {
			return hashcode;
		}

		@Override
		public boolean equals(Object other) {
			Object obj = get();
			if (obj != null) {
				return obj == ((WeakIdKey) other).get();
			} else {
				return this == other;
			}
		}
	}

	// Used by test_jy_internals
	public int _internal_map_size() {
		return objHashcodeToPyId.size();
	}

	public void put(Object key, Object val) {
		cleanup();
		objHashcodeToPyId.put(new WeakIdKey(key), val);
	}

	public Object get(Object key) {
		cleanup();
		return objHashcodeToPyId.get(new WeakIdKey(key));
	}

	public void remove(Object key) {
		cleanup();
		objHashcodeToPyId.remove(new WeakIdKey(key));
	}

	public static void main(String[] args) throws InterruptedException {
		WeakIdentityMap map = new WeakIdentityMap();
		map.put("1", "a");
		map.put(new Object(), "b");
		map.put(new Object(), "2");
		System.gc();
		Thread.sleep(1000);
		map.put("1", "a");
		
	}
}



参考:http://zhang-xzhi-xjtu.iteye.com/blog/413159

你可能感兴趣的:(ReferenceQueue)