论坛首页 Java企业应用论坛

Google Collections(Guava)中强大的Concurrent MapMaker

浏览 23737 次
该帖已经被评为良好帖
作者 正文
   发表时间:2010-05-21  
恩,没问题的。一会我单独开个帖子,发个完整的。



package cn.agrael.collection;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.Reference;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import cn.agrael.ref.FinalizablePhantomReference;
import cn.agrael.ref.FinalizableReference;
import cn.agrael.ref.FinalizableSoftReference;
import cn.agrael.ref.FinalizableWeakReference;
import cn.agrael.util.Assert;

/**
 * 支持各种引用类型的 Map。
 * <p>
 * 引用类型请参考 {@link java.lang.ref}与 {@link cn.agrael.ref} 的描述。
 * </p>
 * <p>
 * 该 Map 的特性和 {@link ConcurrentHashMap} 一样。在第一次调用 put/putAll
 * 方法时(仅仅是在同一个类加载器中的第一次
 * ,如果为同一类加载器,那么在put/putAll后,新创建的实例的put/putAll也不算做第一次),会有一个后台线程随之创建并启动
 * ,该后台线程主要作用和垃圾回收交互,进行回收对象的清理。在清理 键
 * 的同时,会一同清理掉 键的引用包装器 以及 值 和 值的引用包装器 以及 印射 ,在清理 值 时 ,会一同清理掉 值的引用包装器,然后从 Map 中移除印射到自身的 键 以及 印射 。
 * </p>
 * <p>
 * 该清理是 异步 且 “即时” 的,会在垃圾回收的同时清理,不需要在下次对该 Map 操作时才清理包装引用的实例。
 * </p>
 * 
 * @author <a href="http://www.agrael.cn">李翔</a>
 * 
 * @param <K>
 *            此映射维护的键类型
 * @param <V>
 *            映射值的类型
 */
public class ReferenceMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {

	/** 版本号 */
	private static final long serialVersionUID = -6254917146703219097L;

	private final ReferenceKeyType keyReferenceType;
	
	private final ReferenceValueType valueReferenceType;
	
	private transient int initialCapacity = 16;
	
    private transient float loadFactor = 0.75f;
    
    private transient int concurrencyLevel = 16;
	
	private transient ConcurrentMap<Object, Object> map;
	
	/**
	 * 通过指定的 key引用类型 和 value引用类型 创建一个带有默认初始容量、加载因子和 concurrencyLevel 的新的空映射。
	 * @param keyReferenceType key引用类型 。
	 * @param valueReferenceType value引用类型。
	 */
	public ReferenceMap(ReferenceKeyType keyReferenceType ,ReferenceValueType valueReferenceType) {
		this.keyReferenceType = keyReferenceType;
		this.valueReferenceType = valueReferenceType;
		map = new ConcurrentHashMap<Object, Object>(initialCapacity,loadFactor,concurrencyLevel);
	}

	/**
	 * 通过指定的 key引用类型 和 value引用类型 创建一个带有指定初始容量、默认加载因子和 concurrencyLevel 的新的空映射。
	 * @param keyReferenceType key引用类型。
	 * @param valueReferenceType value引用类型。
	 * @param initialCapacity 初始容量。该实现执行内部大小调整,以容纳这些元素。
	 */
	public ReferenceMap(ReferenceKeyType keyReferenceType ,ReferenceValueType valueReferenceType,
			int initialCapacity) {
		this.keyReferenceType = keyReferenceType;
		this.valueReferenceType = valueReferenceType;
		this.initialCapacity = initialCapacity;
		map = new ConcurrentHashMap<Object, Object>(initialCapacity,loadFactor,concurrencyLevel);
	}
	
	/**
	 * 通过指定的 key引用类型 和 value引用类型 创建一个带有指定初始容量、加载因子和并发级别的新的空映射。 
	 * @param keyReferenceType key引用类型。
	 * @param valueReferenceType value引用类型。
	 * @param initialCapacity 初始容量。该实现执行内部大小调整,以容纳这些元素。
	 * @param loadFactor 加载因子阈值,用来控制重新调整大小。在每 bin 中的平均元素数大于此阈值时,可能要重新调整大小。
	 * @param concurrencyLevel 当前更新线程的估计数。该实现将执行内部大小调整,以尽量容纳这些线程。
	 */
	public ReferenceMap(ReferenceKeyType keyReferenceType ,ReferenceValueType valueReferenceType,
			int initialCapacity, float loadFactor, int concurrencyLevel) {
		this.keyReferenceType = keyReferenceType;
		this.valueReferenceType = valueReferenceType;
		this.concurrencyLevel = concurrencyLevel;
		this.initialCapacity = initialCapacity;
		this.loadFactor = loadFactor;
		map = new ConcurrentHashMap<Object, Object>(initialCapacity,
				loadFactor, concurrencyLevel);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<K> keySet() {
		if(keyReferenceType == ReferenceKeyType.STRONG){
			// 如果为强引用,则 map 中的 keySet 就是需要的
			return (Set<K>) map.keySet();
		}
		// 为其他引用
		return new AbstractSet<K>() {

			public Iterator<K> iterator() {
				return new Iterator<K>() {
					private Iterator<Object> iterator = map.keySet().iterator();
					public boolean hasNext() {
						return iterator.hasNext();
					}

					public K next() {
						return getKey(iterator.next());
					}

					public void remove() {
						iterator.remove();
					}
					
				};
			}

			public int size() {
				return map.size();
			}
			
		};
	}

	@Override
	public void clear() {
		map.clear();
	}

	@Override
	public V remove(Object key) {
		Assert.notNull(key);
		Object keyReference = createKeyReferenceWrapper(key);
		Object returnValueReference = map.remove(keyReference);
		return getValue(returnValueReference);
	}

	@Override
	public boolean containsKey(Object key) {
		return map.containsKey(key);
	}

	@Override
	public int size() {
		return map.size();
	}

	@Override
	public boolean isEmpty() {
		return map.isEmpty();
	}

	@Override
	public V put(K key, V value) {
		Assert.notNull(key);
		Assert.notNull(value);
		Object keyReference = null;
		switch (keyReferenceType) {
		case STRONG:
			keyReference = key;
			break;
		case SOFT:
			keyReference = new FinalizableKeySoftReference<K>(key);
			break;
		case WEAK:
			keyReference = new FinalizableKeyWeakReference<K>(key);
			break;
		case PHANTOM:
			keyReference = new FinalizableKeyPhantomReference<K>(key);
			break;
		}
		Object valueReference = null;
		switch (valueReferenceType) {
		case STRONG:
			valueReference = value;
			break;
		case SOFT:
			valueReference = new FinalizableValueSoftReference<V>(keyReference ,value);
			break;
		case WEAK:
			valueReference = new FinalizableValueWeakReference<V>(keyReference ,value);
			break;
		case PHANTOM:
			valueReference = new FinalizableValuePhantomReference<V>(keyReference ,value);
			break;
		}
		Object returnValueReference = map.put(keyReference, valueReference);
		if(returnValueReference == null){
			return null;
		}
		return getValue(returnValueReference);
	}
	
	
	@SuppressWarnings("unchecked")
	private V getValue(Object valueReference){
		return (V) (valueReferenceType == ReferenceValueType.STRONG ? valueReference : valueReference == null ? null : ((Reference<V>) valueReference).get());
	}
	
	
	@SuppressWarnings("unchecked")
	private K getKey(Object keyReference){
		return (K) (keyReferenceType == ReferenceKeyType.STRONG ? keyReference : keyReference == null ? null : ((Reference<K>) keyReference).get());
	}
	
	/**
	 * 创建 Key 的印射包装器。
	 * @param key 要创建印射包装器的 key。
	 * @return 如果是强引用,返回 key 本身,否则返回  Key 的印射包装器。
	 */
	private Object createKeyReferenceWrapper(Object key){
		return keyReferenceType == ReferenceKeyType.STRONG ? key : new KeyReferenceWrapper(key);
	}
	
	/**
	 * 得到 key 在内存中的地址的 hashCode。
	 * @param key 要得到在内存中的地址的 hashCode 的 key。
	 * @return key 在内存中的地址的 hashCode。
	 * @see System#identityHashCode(Object)
	 */
	private int keyHashCode(Object key){
		return System.identityHashCode(key);
	}
	
	
	private boolean referenceEquals(Reference<?> reference , Object object){
		if(reference == object){
			// 直接引用相同
			return true;
		}
		if(reference == null){
			// 一方为 null 则返回 false(因为上个判断结合这个判断,object 一定不为 null)
			return false;
		}
		if(object instanceof Reference<?>){
			// object 为引用类型,则比较引用类型中的值的引用
			Object referenceValue = ((Reference<?>) object).get();
			return referenceValue != null && reference.get() == referenceValue;
		}
		if(object instanceof KeyReferenceWrapper){
			// object为 key 引用包装类型
			return ((KeyReferenceWrapper) object).getReference() == reference.get();
		}
		return false;
	}

	@Override
	public V get(Object key) {
		Assert.notNull(key);
		Object keyReference = createKeyReferenceWrapper(key);
		Object returnValueReference = map.get(keyReference);
		return getValue(returnValueReference);
	}

	public Set<Entry<K, V>> entrySet() {
		return new AbstractSet<Entry<K, V>>() {

			public Iterator<Entry<K, V>> iterator() {
				return new Iterator<Entry<K, V>>() {
					private Iterator<Entry<Object, Object>> iterator = map.entrySet().iterator();

					public boolean hasNext() {
						return iterator.hasNext();
					}

					public Entry<K, V> next() {
						final Entry<Object, Object> entry = iterator.next();
						return new Entry<K, V>() {

							public K getKey() {
								return ReferenceMap.this.getKey(entry.getKey());
							}

							public V getValue() {
								return ReferenceMap.this.getValue(entry.getValue());
							}

							public V setValue(V value) {
								throw new UnsupportedOperationException("不支持的操作。");
							}

						};
					}

					public void remove() {
						iterator.remove();
					}

				};
			}

			public int size() {
				return map.size();
			}

		};
	}
	
	/**
	 * 弱引用对象的键类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableKeyWeakReference<T> extends FinalizableWeakReference<T> implements FinalizableReference<T>{

		private final int hashCode;
		
		/**
		 * 构造一个新的 弱引用对象的键类 实例。
		 * @param referent 键。
		 */
		protected FinalizableKeyWeakReference(T referent) {
			super(referent);
			this.hashCode = keyHashCode(referent);
		}

		public void finalizeReferent() {
			map.remove(this);
		}

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

		@Override
		public boolean equals(Object object) {
			return referenceEquals(this, object);
		}
	}
	
	/**
	 * 弱引用对象的值类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableValueWeakReference<T> extends FinalizableWeakReference<T> implements FinalizableReference<T>{
		
		private Object keyReference;
		
		/**
		 * 构造一个新的 弱引用对象的值类 实例。
		 * @param keyReference 与此值关联的 键 。
		 * @param referent 值。
		 */
		protected FinalizableValueWeakReference(Object keyReference ,T referent) {
			super(referent);
			this.keyReference = keyReference;
		}
		
		public void finalizeReferent() {
			map.remove(keyReference,this);
		}
	}
	
	/**
	 * 软引用对象的键类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableKeySoftReference<T> extends FinalizableSoftReference<T> implements FinalizableReference<T>{

		private final int hashCode;
		
		/**
		 * 构造一个新的 软引用对象的键类 实例。
		 * @param referent 键。
		 */
		protected FinalizableKeySoftReference(T referent) {
			super(referent);
			this.hashCode = keyHashCode(referent);
		}

		public void finalizeReferent() {
			map.remove(this);
		}

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

		@Override
		public boolean equals(Object object) {
			return referenceEquals(this, object);
		}
	}
	
	/**
	 * 软引用对象的值类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableValueSoftReference<T> extends FinalizableSoftReference<T> implements FinalizableReference<T>{
		
		private Object keyReference;
		
		/**
		 * 构造一个新的 软引用对象的值类 实例。
		 * @param keyReference 与此值关联的 键 。
		 * @param referent 值。
		 */
		protected FinalizableValueSoftReference(Object keyReference ,T referent) {
			super(referent);
			this.keyReference = keyReference;
		}
		
		public void finalizeReferent() {
			map.remove(keyReference,this);
		}
	}
	

	
	/**
	 * 虚引用对象的键类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableKeyPhantomReference<T> extends FinalizablePhantomReference<T> implements FinalizableReference<T>{

		private final int hashCode;
		
		/**
		 * 构造一个新的 虚引用对象的键类 实例。
		 * @param referent 键。
		 */
		protected FinalizableKeyPhantomReference(T referent) {
			super(referent);
			this.hashCode = keyHashCode(referent);
		}

		public void finalizeReferent() {
			map.remove(this);
		}

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

		@Override
		public boolean equals(Object object) {
			return referenceEquals(this, object);
		}
	}
	
	/**
	 * 虚引用对象的值类。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 * @param <T> 引用类型
	 */
	protected class FinalizableValuePhantomReference<T> extends FinalizablePhantomReference<T> implements FinalizableReference<T>{
		
		private Object keyReference;
		
		/**
		 * 构造一个新的 虚引用对象的值类 实例。
		 * @param keyReference 与此值关联的 键 。
		 * @param referent 值。
		 */
		protected FinalizableValuePhantomReference(Object keyReference ,T referent) {
			super(referent);
			this.keyReference = keyReference;
		}
		
		public void finalizeReferent() {
			map.remove(keyReference,this);
		}
	}
	
	/**
	 * 引用类型中的对象的另一个包装器,该包装器实现为引用类型中的对象保持 put 与 get 时用到的 hashCode 和 equals 方法的一致性。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 */
	protected static class ReferenceWrapper{
		
		protected final Object reference;
		
		/**
		 * 使用一个引用类型中的对象实例构造一个新的包装器。
		 * @param reference 要包装的引用类型中的对象实例。
		 */
		protected ReferenceWrapper(Object reference) {
			this.reference = reference;
		}

		/**
		 * 得到被包装的对象。
		 * @return 被包装的对象。
		 */
		protected Object getReference() {
			return reference;
		}

		/**
		 * 调用包装对象的 hashCode 方法。
		 * @return 包装对象的 hashCode。
		 */
		@Override
		public int hashCode() {
			return reference.hashCode();
		}

		/**
		 * 调用包装对象的  equals 方法比较。
		 * @param obj 要与之比较的对象。
		 * @return 如果传入的对象和包装对象“相等”则返回 true,否则返回 false。
		 */
		@Override
		public boolean equals(Object obj) {
			// 使用包装对象的 equals
			return reference.equals(obj);
		}
	}
	
	/**
	 * 专用于  key 的引用类型中的对象的另一个包装器。该包装器重写了 hashCode 方法,使用 {@link System#identityHashCode(Object)} 取得 hash值 。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 */
	protected static class KeyReferenceWrapper extends ReferenceWrapper {

		/**
		 * 使用一个引用类型中的 key对象实例 构造一个新的包装器。
		 * @param reference 要包装的引用类型中的key对象实例。
		 */
		protected KeyReferenceWrapper(Object reference) {
			super(reference);
		}
		
		/**
		 * 返回包装的 Key 的内存里的 hashCode。
		 * @return 包装的 Key 的内存里的 hashCode。
		 * @see System#identityHashCode(Object)
		 */
		@Override
		public int hashCode() {
			// 这里要认为同一内存地址的才是相同对象,所以取得内存地址中的 HASH码
			return System.identityHashCode(reference);
		}
	}
	
	/**
	 * 用作 K 的引用类型。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 */
	public static enum ReferenceKeyType {
		
		/** 强引用 */
		STRONG(Object.class),
		
		/** 软引用 */
		SOFT(ReferenceMap.FinalizableKeySoftReference.class),
		
		/** 弱引用 */
		WEAK(ReferenceMap.FinalizableKeyWeakReference.class),
		
		/** 虚引用 */
		PHANTOM(ReferenceMap.FinalizableKeyPhantomReference.class);
		
		private final Class<?> referenceTypeClass;

		private ReferenceKeyType(Class<?> referenceTypeClass) {
			this.referenceTypeClass = referenceTypeClass;
		}
		
		Class<?> getReferenceTypeClass(){
			return referenceTypeClass;
		}
	}
	
	/**
	 * 用作 V 的引用类型。
	 * @author <a href="http://www.agrael.cn">李翔</a>
	 *
	 */
	public static enum ReferenceValueType {
		
		/** 强引用 */
		STRONG(Object.class),
		
		/** 软引用 */
		SOFT(ReferenceMap.FinalizableValueSoftReference.class),
		
		/** 弱引用 */
		WEAK(ReferenceMap.FinalizableValueWeakReference.class),
		
		/** 虚引用 */
		PHANTOM(ReferenceMap.FinalizableValuePhantomReference.class);
		
		private final Class<?> referenceTypeClass;
		
		private ReferenceValueType(Class<?> referenceTypeClass) {
			this.referenceTypeClass = referenceTypeClass;
		}
		
		Class<?> getReferenceTypeClass(){
			return referenceTypeClass;
		}
	}
	
	private void writeObject(ObjectOutputStream out) throws IOException  {
	    out.defaultWriteObject();
	    out.writeInt(size());
	    out.writeFloat(loadFactor);
	    out.writeInt(concurrencyLevel);
	    for (Map.Entry<Object, Object> entry : map.entrySet()) {
	      Object key = getKey(entry.getKey());
	      Object value = getValue(entry.getValue());

	      if (key != null && value != null) {
	        out.writeObject(key);
	        out.writeObject(value);
	      }
	    }
	    out.writeObject(null);
	  }

	  @SuppressWarnings("unchecked")
	private void readObject(ObjectInputStream in) throws IOException,
	      ClassNotFoundException {
	    in.defaultReadObject();
	    int size = in.readInt();
	    float loadFactor = in.readFloat();
	    int concurrencyLevel = in.readInt();
	    this.initialCapacity = size;
	    this.map = new ConcurrentHashMap<Object, Object>(size,loadFactor,concurrencyLevel);
	    while (true) {
	      K key = (K) in.readObject();
	      if (key == null) {
	        break;
	      }
	      V value = (V) in.readObject();
	      put(key, value);
	    }
	  }
}

0 请登录后投票
   发表时间:2010-05-21   最后修改:2010-05-21
我已经发了一篇名叫《封装ConcurrentHashMap使其成为具有各种引用类型key与value的ReferenceMap》的帖子,那个是完整的介绍。
0 请登录后投票
   发表时间:2010-05-21  
从来没用过。学习一下。多谢LZ
0 请登录后投票
   发表时间:2010-05-21   最后修改:2010-05-21
回Agrael:

你研究精神值得我们学习,帖的代码看了一些,参考了很多现成的代码,连Magic Number都复制过来了,而且FinalizableReference这些的类,很眼熟,不知道你为什么不用现成的,要把人家的包名改改复制到自己的项目里用,并且你这个Map还有提高的空间,既然是ConcurrentMap就应该实现ConcurrentMap接口,否则putIfAbsent这种方法都没有,用起来也不方便,替代WeakHashMap或许可以,但是和拥有ComputingMap的MapMaker比,呵呵呵。
0 请登录后投票
   发表时间:2010-05-21  
Norther 写道
回Agrael:

你研究精神值得我们学习,帖的代码看了一些,参考了很多现成的代码,连Magic Number都复制过来了,而且FinalizableReference这些的类,很眼熟,不知道你为什么不用现成的,要把人家的包名改改复制到自己的项目里用,并且你这个Map还有提高的空间,既然是ConcurrentMap就应该实现ConcurrentMap接口,否则putIfAbsent这种方法都没有,用起来也不方便,替代WeakHashMap或许可以,但是和拥有ComputingMap的MapMaker比,还差一截。


呵呵,你所包名改改这个我觉得我没这样做,如果我改包名的话,也是cn.agrael.原包名。
这个ReferenceMap我修改过无数次,最终形成了现在的版本。
在这个版本之前,我发现了XWORK里也有类似的东西,而且比我写得更好,所以我就参考着修改了下,修改的仅仅是从之前的每次创建一个ReferenceMap都有一个线程清理变到无论创建多少个ReferenceMap都只有一个线程清理。
至于FinalizableReference命名这个,我想说的是,这个名字还不是我自己命的,是我国外一个朋友帮我命的,我英语不好,所以叫他帮忙取的。呵呵。
0 请登录后投票
   发表时间:2010-05-21  
就之前我一直被WeakHashMap的并发问题困扰,在可能2年前吧,就准备封装ConcurrentHashMap来满足需求,但是当时到处找都没找到自己需要的,所以才自己写了个,经过很多次修改,最终才比较满意。后来发现XWORK里的时,已经和现在的代码区别不大了。至于为什么不实现ConcurrentMap。这个的话我觉得都到这一步了,如果哪天需要在ReferenceMap中单独出现这些方法的话,再改也没什么,毕竟现在我还有个CollectionUtils配合这个使用,呵呵。
0 请登录后投票
   发表时间:2010-05-21  
Agrael 写道
Norther 写道
回Agrael:

你研究精神值得我们学习,帖的代码看了一些,参考了很多现成的代码,连Magic Number都复制过来了,而且FinalizableReference这些的类,很眼熟,不知道你为什么不用现成的,要把人家的包名改改复制到自己的项目里用,并且你这个Map还有提高的空间,既然是ConcurrentMap就应该实现ConcurrentMap接口,否则putIfAbsent这种方法都没有,用起来也不方便,替代WeakHashMap或许可以,但是和拥有ComputingMap的MapMaker比,还差一截。


呵呵,你所包名改改这个我觉得我没这样做,如果我改包名的话,也是cn.agrael.原包名。
这个ReferenceMap我修改过无数次,最终形成了现在的版本。
在这个版本之前,我发现了XWORK里也有类似的东西,而且比我写得更好,所以我就参考着修改了下,修改的仅仅是从之前的每次创建一个ReferenceMap都有一个线程清理变到无论创建多少个ReferenceMap都只有一个线程清理。
至于FinalizableReference命名这个,我想说的是,这个名字还不是我自己命的,是我国外一个朋友帮我命的,我英语不好,所以叫他帮忙取的。呵呵。



你国外的朋友不会是Bob Lee吧?强的!

http://code.google.com/p/google-collections/source/browse/trunk/src/com/google/common/base/FinalizablePhantomReference.java
0 请登录后投票
   发表时间:2010-05-21  
Norther 写道
Agrael 写道
Norther 写道
回Agrael:

你研究精神值得我们学习,帖的代码看了一些,参考了很多现成的代码,连Magic Number都复制过来了,而且FinalizableReference这些的类,很眼熟,不知道你为什么不用现成的,要把人家的包名改改复制到自己的项目里用,并且你这个Map还有提高的空间,既然是ConcurrentMap就应该实现ConcurrentMap接口,否则putIfAbsent这种方法都没有,用起来也不方便,替代WeakHashMap或许可以,但是和拥有ComputingMap的MapMaker比,还差一截。


呵呵,你所包名改改这个我觉得我没这样做,如果我改包名的话,也是cn.agrael.原包名。
这个ReferenceMap我修改过无数次,最终形成了现在的版本。
在这个版本之前,我发现了XWORK里也有类似的东西,而且比我写得更好,所以我就参考着修改了下,修改的仅仅是从之前的每次创建一个ReferenceMap都有一个线程清理变到无论创建多少个ReferenceMap都只有一个线程清理。
至于FinalizableReference命名这个,我想说的是,这个名字还不是我自己命的,是我国外一个朋友帮我命的,我英语不好,所以叫他帮忙取的。呵呵。



你国外的朋友不会是Bob Lee吧?强的!

http://code.google.com/p/google-collections/source/browse/trunk/src/com/google/common/base/FinalizablePhantomReference.java



绝对不是,而且当时我参考的也不是这个包的东西。
0 请登录后投票
   发表时间:2010-05-21  
org.apache.commons.collections.map.ReferenceMap.java
此类在  commons-collections-3.2.1.jar
不知楼主有没有看过此类,并 和你自己所写有什么区别?
0 请登录后投票
   发表时间:2010-05-21  
JavaYwsEye 写道
org.apache.commons.collections.map.ReferenceMap.java
此类在  commons-collections-3.2.1.jar
不知楼主有没有看过此类,并 和你自己所写有什么区别?

我想你是问的我,不是楼主。
上面我就说了,不过我不知道你说的这个类,我看的是Xwork里的一个类,在我new一个实例就创建一个线程困扰的时候,看到那个类后把new一个实例就创建一个线程改为了只会有一个线程,除此之外,这个ReferenceMap已经和我发的代码差不多了。如果有相似的,我估计是思想大同小异吧。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics