WeakHashMap使用小计

     在单机版系统中需要实现一个简单的缓存功能(不使用分布式缓存系统),在内存中用一个map来实现就行了,通常的map可用 LinkedHashMap也可以用WeakHashMap 来实现,他们的区别在于淘汰机制上,前者是在构建时设置一个阀值(或者是可以在回收的时候决定那个对象优先被回收),当到了一个阀值之后就会决定老的对象是否要被淘汰。而后者WeakHashMap 是基于虚拟机的垃圾回机制来淘汰的,回收时,容器中哪个对象对回收完全是由GC来决定的。

    这里通过一些代码来来说明WeakHashMap的特性,首先第一个代码,可以顺利执行完成:

	public void test1() throws Exception {
		//List<byte[][]> keys = new ArrayList<byte[][]>();
		byte[][] key = null;
		WeakHashMap<byte[][], byte[][]> maps = new WeakHashMap<byte[][], byte[][]>();
		for (int i = 0; i < 10000; i++) {
			key = new byte[1000][1000];
			
			maps.put(key, new byte[1000][1000]);

			// System.gc();
			System.err.println(i);

			System.err.println(" size" + maps.size());

		}
	}

   从输出结果上可以发现,size的大小,会由小变大,突然变小,然后再由小变大。这个说明垃圾回收期在器作用,这个和jdk的说明文档是一致的:

/ * An entry in a <tt>WeakHashMap</tt> will automatically be removed when
 * its key is no longer in ordinary use.  More precisely, the presence of a
 * mapping for a given key will not prevent the key from being discarded by the
 * garbage collector, that is, made finalizable, finalized, and then reclaimed.
 * When a key has been discarded its entry is effectively removed from the map,
 * so this class behaves somewhat differently from other <tt>Map</tt>
 * implementations.
*/

当GC开始回收的时候会发现,map的key已经不被使用了,即使map中key和value的映射已然存在,也不能阻止map的key被GC回收掉。当map的key被回收了之后,value对象也会被顺利地回收的。

再看下面这个代码:

	public void test2() throws Exception {
		List<byte[][]> keys = new ArrayList<byte[][]>();
		byte[][] key = null;
		WeakHashMap<byte[][], byte[][]> maps = new WeakHashMap<byte[][], byte[][]>();
		for (int i = 0; i < 10000; i++) {
			key = new byte[1000][1000];
			keys.add(key);
			maps.put(key, new byte[1000][1000]);

			// System.gc();
			System.err.println(i);

			System.err.println(" size" + maps.size());

		}
	}

 test2()执行到一半就会抛出OOM异常,这份代码和上一份代码的唯一区别就是,map的key放到一个list中,这样能保证方法体中的所有key都是被引用的,所以在启动垃圾回收的时候,weak中的key一个都不会被自动回收,所以OOM就在所难免了。

   

    所以在使用WeakHashMap的时候,千万注意,使用完某个key如果希望对象会被自动回收,需要与map的key的所有引用关系切断。

猜你喜欢

转载自mozhenghua.iteye.com/blog/2261790