package jef.common.pool; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import com.google.common.collect.MapMaker; /** * 高性能重入对象池实现 * * 支持重入 * @author jiyi * */ public final class ReentrantPool<T> extends SimplePool<T>{ //重入记录 final Map<Object, Wrapper<T>> map = new MapMaker().concurrencyLevel(12).weakKeys().makeMap(); private final AtomicLong pollCount = new AtomicLong(); private final AtomicLong offerCount = new AtomicLong(); /** * 构造 * @param fac 重入对象 * @param min * @param max */ public ReentrantPool(ObjectFactory<T> fac,int min,int max){ super(fac,min,max); } public T poll() { pollCount.incrementAndGet(); Thread user = Thread.currentThread(); Wrapper<T> conn = map.get(user); if (conn == null) { conn = new Wrapper<T>(super.poll()); map.put(user, conn); conn.setUsedByObject(user); } else { conn.addUsedByObject(); } return conn.obj; } public void offer(T o) { offerCount.incrementAndGet(); Thread user = Thread.currentThread(); Wrapper<T> conn = map.get(user); if(conn==null || conn.obj!=o){//不是在同一个线程中归还,问题复杂了。 conn=null; for(Wrapper<T> w:map.values()){ if(w.obj==o){ conn=w; } } if(conn==null){//无法定位该记录是否重入。。。 throw new IllegalStateException("The object "+o+" is unknown in reentrant map."); } } Object u = conn.popUsedByObject(); if (u == null) return;// 不是真正的归还 Wrapper<T> conn1 = map.remove(u); if (conn1 != conn) { //never happens. throw new IllegalStateException("The connection returned not match."); } super.offer(conn1.obj); } public void closePool() { super.closePool(); for(Wrapper<T> wrapper:map.values()){ T obj=wrapper.obj; if(obj!=null){ factory.release(obj); } } } /** * 获得对象池状态 * * @return */ public PoolStatus getStatus() { PoolStatus st=super.getStatus(); st.setOfferCount(offerCount.get()); st.setPollCount(pollCount.get()); return st; } private static class Wrapper<T>{ private T obj; private volatile Object used; private volatile int count; public Wrapper(T create) { this.obj=create; } void setUsedByObject(Object user) { this.used=user; count++; } Object popUsedByObject() { if(--count>0){ //log.debug("不是真正的归还{}还有{}次使用.",used,count); return null; }else{ Object o=used; used=null; return o; } } void addUsedByObject() { count++; } } }