频道栏目
首页 > 资讯 > 其他综合 > 正文

apache commons pool之GenericObjectPool分析(通用对象池技术)

16-05-02        来源:[db:作者]  
收藏   我要投稿

在高并发的环境下写程序时通常碰到线程安全的问题,当然,最能想到的就是加锁,再进一步想就是池子了,所谓池子就是,里面可以放置多个同样的对象,每个线程需要用时,就从池中取走,用完时再放回到池中,即可解决线程的安全问题,又可提高速度(预先初始化)。

 

当然若是自己写个对象池的话,也是可以的,不过现在有个通用的apache下的commons-pool框架,个人感觉真是不错,尤其是现在我们用到的java框架里面,为我们省去了不少的开发成本。

官方网址:http://commons.apache.org/proper/commons-pool/

 

本文,我先只讲下通用的GenericObjectPool的原理及使用技巧。

 

1、主要组成类

1.1PooledObject(可被池化的对象)

默认实现DefaultPooledObject,里面封装了一个真正的用户需要池化的对象object。

 

 

其中DefaultPooledObject里面有两个方法,感觉非常秒

1、Exception borrowedBy :用于记录上次调用borrow时的堆栈,用于跟踪代码调用情况。

 

 @Override
    public synchronized boolean allocate() {
        if (state == PooledObjectState.IDLE) {
            state = PooledObjectState.ALLOCATED;
            lastBorrowTime = System.currentTimeMillis();
            lastUseTime = lastBorrowTime;
            borrowedCount++;
            if (logAbandoned) {
                borrowedBy = new AbandonedObjectCreatedException();
            }
            return true;
        } else if (state == PooledObjectState.EVICTION) {
            // TODO Allocate anyway and ignore eviction test
            state = PooledObjectState.EVICTION_RETURN_TO_HEAD;
            return false;
        }
        // TODO if validating and testOnBorrow == true then pre-allocate for
        // performance
        return false;
    }


 

2、Exception usedBy: 同上,记录use时的堆栈

 

  @Override
    public void use() {
        lastUseTime = System.currentTimeMillis();
        usedBy = new Exception("The last code to use this object was:");
    }

 

1.2、PooledObjectState

 

对象的状态,也即生命周期

allocated:即为此对象被客户端使用中

idle:在池中,处于空闲状态

eviction:在实例化GenericObjectPool对象时,内部会启动一个EvictionTimer线程线程,定期(timeBetweenEvictionRunsMillis)执行evict方法,以EvictionPolicy策略destory 状态处于idle过长的对象或idle数太多的时候。

abandoned:当池中的对象被客户端拿出后,若长时间(removeAbandonedTimeout)未返回池中,或没有调用use方法,即被标记为抛弃的,当执行removeAbandoned方法时从池中destory,并若logAbandoned为true的话,则打印调用堆栈

 

 

1.3PooledObjectFactory(对象创建工厂)

一般需要程序员继承BasePooledObjectFactory,创建需要池化的对象,如

 

protected class NaviPoolableObjectFactory extends BasePooledObjectFactory {

		private Class handleClass;
		private String auth;
		private ServerUrl server;

		public NaviPoolableObjectFactory(Class handleClass,
				ServerUrl server, String auth) {
			this.handleClass = handleClass;
			this.auth = auth;
			this.server = server;
		}

		@Override
		public INaviDriver create() throws Exception {
			return (INaviDriver)BeanUtils.instantiateClass(handleClass
					.getDeclaredConstructor(ServerUrl.class, String.class,
							NaviPoolConfig.class), this.server, this.auth,
					poolConfig);
		}

		@Override
		public void destroyObject(PooledObject p) throws Exception {
			p.getObject().destroy();
		}

		@Override
		public boolean validateObject(PooledObject p) {
			try{
				return p.getObject().isAlive();
			}catch(Exception e){
				return false;
			}
		}

		@Override
		public PooledObject wrap(INaviDriver obj) {
			return new DefaultPooledObject(obj);
		}
	}

 


1.4GenericObjectPoolConfig(对象池配置)

 

实例化GenericObjectPool需要的配置bean

lifo:后进先出,或者先进先出

maxWaitMillis:从idle队列里面取对象时,若阻塞的话,则最大等待时长

minEvictableIdleTimeMillis:处于idle状态超过此值时,会被destory

softMinEvictableIdleTimeMillis:处于idle状态超过此值,且处于idle状态个数大于minIdle时会被destory ,正常情况下softMinEvictableIdleTimeMillis

numTestsPerEvictionRun: evict线程每次遍历时evict的个数

testOnCreate:当create对象时,是否测试池化的对象是否存活

testOnBorrow: 同上,从池中borrow出来时测试

testOnReturn:同上,归还池中时测试

testWhileIdle:同上,idle状态时测试

timeBetweenEvictionRunsMillis:evict线程每次间隔时间

blockWhenExhausted:从池中取对象时,若池子用尽的话,是否阻塞等待一会maxWaitMillis

jmxEnabled:jmx是否开启监控

 

1.5AbandonedConfig(防止对象泄露)

abandoned:被抛弃的,即被池抛弃的设置(客户端从池里面取出去后,若长时间不归还池中,则抛弃并destory)并通过配置可以设置是否logAbandoned,若true的话,则把抛弃对象时,打印相关的日志(调用日志)

 

1.6ObjectPool(对象池)

对象池接口,客户端引用

 

1.7GenericObjectPool(通用对象池实现)

GenericObjectPool 继承BaseGenericObjectPool,并实现了ObjectPool、GenericObjectPoolMXBean、UsageTracking接口

 

 public GenericObjectPool(PooledObjectFactory factory,
            GenericObjectPoolConfig config) {

        super(config, ONAME_BASE, config.getJmxNamePrefix());

        if (factory == null) {
            jmxUnregister(); // tidy up
            throw new IllegalArgumentException("factory may not be null");
        }
        this.factory = factory;

        setConfig(config);

        startEvictor(getTimeBetweenEvictionRunsMillis());
    }

 

2、主要流程

 

2.1 evict线程流程

虚线箭头表示方法内部调用。
 

 

2.2 完整类图

 

 

相关TAG标签
上一篇:STL算法_set相关算法篇
下一篇:面试之路(18)-java的函数参数传递类型之值传递还是引用传递
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站