commons-pool实战之 GenericObjectPool和GenericKeyedObjectPool
前面两篇文章说了怎么样简单的使用commons-pool库,这里需要考虑一个问题就是在很多时候我们在池里的对象都是比较重型的并且大多数比较稀缺的 资源,比如说数据库连接,这样如果一直把一些连接放在池里不归还,就会很占资源,并且是这些资源利用率降低,那么怎样才能更好的管理池子中的资源 呢,commons-pool里提供了一个GenericObjectPool类,它的出现使上面的问题就迎刃而解了。同样对于 GenericObjectPool类,也就有一个对应的GenericKeyedObjectPool类。
下面还是例子说话
一个Connection类,可以想象成一个远程连接比如数据库连接等。其中包括创建连接,关闭连接,和一个print方法。
- package com.googlecode.garbagecan.commons.pool.sample3;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class MyConnection {
- private static Logger logger = LoggerFactory.getLogger(MyConnection.class);
- private String name;
- private boolean connected;
- public MyConnection(String name) {
- this.name = name;
- }
- public void connect() {
- this.connected = true;
- logger.info(name + ": " + connected);
- }
- public void close() {
- this.connected = false;
- logger.info(name + ": " + connected);
- }
- public boolean isConnected() {
- return this.connected;
- }
- public String getName() {
- return this.name;
- }
- public void print() {
- logger.info(this.name);
- }
- }
一个PoolableObjectFactory接口的实现类,提供makeObject, activateObject, passivateObject, validateObject, destroyObject方法。
- package com.googlecode.garbagecan.commons.pool.sample3;
- import org.apache.commons.pool.PoolableObjectFactory;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class MyConnectionPoolableObjectFactory implements PoolableObjectFactory {
- private static Logger logger = LoggerFactory.getLogger(MyConnectionPoolableObjectFactory.class);
- private static int count = 0;
- public Object makeObject() throws Exception {
- MyConnection myConn = new MyConnection(generateName());
- logger.info(myConn.getName());
- myConn.connect();
- return myConn;
- }
- public void activateObject(Object obj) throws Exception {
- MyConnection myConn = (MyConnection)obj;
- logger.info(myConn.getName());
- }
- public void passivateObject(Object obj) throws Exception {
- MyConnection myConn = (MyConnection)obj;
- logger.info(myConn.getName());
- }
- public boolean validateObject(Object obj) {
- MyConnection myConn = (MyConnection)obj;
- logger.info(myConn.getName());
- return myConn.isConnected();
- }
- public void destroyObject(Object obj) throws Exception {
- MyConnection myConn = (MyConnection)obj;
- logger.info(myConn.getName());
- myConn.close();
- }
- private synchronized String generateName() {
- return "conn_" + (++count);
- }
- }
一个测试类
- package com.googlecode.garbagecan.commons.pool.sample3;
- import org.apache.commons.pool.ObjectPool;
- import org.apache.commons.pool.PoolableObjectFactory;
- import org.apache.commons.pool.impl.GenericObjectPool;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- public class Test {
- private static Logger logger = LoggerFactory.getLogger(Test.class);
- public static void main(String[] args) {
- //test1();
- //test2();
- //test3();
- }
- private static void test1() {
- PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
- GenericObjectPool.Config config = new GenericObjectPool.Config();
- config.lifo = false;
- config.maxActive = 5;
- config.maxIdle = 5;
- config.minIdle = 1;
- config.maxWait = 5 * 1000;
- ObjectPool pool = new GenericObjectPool(factory, config);
- for (int i = 0; i < 10; i++) {
- Thread thread = new Thread(new MyTask(pool));
- thread.start();
- }
- //closePool(pool);
- }
- private static void test2() {
- PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
- GenericObjectPool.Config config = new GenericObjectPool.Config();
- config.lifo = false;
- config.maxActive = 5;
- config.maxIdle = 5;
- config.minIdle = 1;
- config.maxWait = 20 * 1000;
- ObjectPool pool = new GenericObjectPool(factory, config);
- for (int i = 0; i < 10; i++) {
- Thread thread = new Thread(new MyTask(pool));
- thread.start();
- }
- //closePool(pool);
- }
- private static void test3() {
- PoolableObjectFactory factory = new MyConnectionPoolableObjectFactory();
- GenericObjectPool.Config config = new GenericObjectPool.Config();
- config.lifo = false;
- config.maxActive = 5;
- config.maxIdle = 0;
- config.minIdle = 0;
- config.maxWait = -1;
- ObjectPool pool = new GenericObjectPool(factory, config);
- Thread thread = new Thread(new MyTask(pool));
- thread.start();
- try {
- Thread.sleep(60L * 1000L);
- } catch (Exception e) {
- e.printStackTrace();
- }
- //closePool(pool);
- }
- private static void closePool(ObjectPool pool) {
- try {
- pool.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private static class MyTask implements Runnable {
- private ObjectPool pool;
- public MyTask(ObjectPool pool) {
- this.pool = pool;
- }
- public void run() {
- MyConnection myConn = null;
- try {
- myConn = (MyConnection)pool.borrowObject();
- try {
- myConn.print();
- } catch(Exception ex) {
- pool.invalidateObject(myConn);
- myConn = null;
- }
- Thread.sleep(10L * 1000L);
- } catch(Exception ex) {
- logger.error("Cannot borrow connection from pool.", ex);
- } finally {
- if (myConn != null) {
- try {
- pool.returnObject(myConn);
- } catch (Exception ex) {
- logger.error("Cannot return connection from pool.", ex);
- }
- }
- }
- }
- }
- }
其中包含了三个方法,分别测试了三种情况;
- 类中包含了一个实现了Runnable接口的内部类,目的是为了启动几个线程来模拟的对连接类的使用,并且为了尽可能的真实,在run方法里sleep了10秒中;
- 首
先运行测试方法test1()可以看到,在循环10个线程申请Connection类时,前面5个可以很好的获取,但是后面5个线程就不能获取连接,并且
抛出了异常,这是由于“config.maxActive = 5;”和“config.maxWait = 5 *
1000;”在起作用,由于配置了最大活动连接是5个,并且后续申请没有有效连接的等待时间是5秒,所以test1方法中后面五个线程在等了5秒后全部抛
出异常,表明不能申请连接了。 - 下面运行test2()方法,在test2中把“config.maxWait = 20 * 1000;”改成了20秒,而我们程序中每个线程使用连接会用去10秒,所以后面五个线程在等待了10秒后就全部获取连接了,所以程序最后会运行成功。
- 再
看test3()方法,其中把maxIdle和minIdle都改为0,就是在连接不用时立即真正归还连接,对于数据库连接来说就是关闭物理连接,而
maxWait改为-1,就是如果没有申请到连接就永远等待,运行test3()方法,观察日志,可以看出程序在用户连接对象以后,会调用
MyConnectionPoolableObjectFactory.destroyObject()和MyConnection.close()方法
来销毁对象。所以如果是使用这样的配置,就相当于每次都是物理连接,用完后就关闭连接。当然这里是一个极端的例子,真实情况下不会把maxIdle和
minIdle都设为0的。
其实对于GenericObjectPool.Config类和GenericKeyedObjectPool.Config类还是有很多配置参数的,这里只是列出的最简单的几个常用的,具体可以参考官方文档。
来源:http://blog.csdn.net/kongxx/article/details/6612760
源码地址:https://github.com/apache/commons-pool
commons-pool实战之 GenericObjectPool和GenericKeyedObjectPool的更多相关文章
- NoClassDefFoundError: org/apache/commons/pool/impl/GenericObjectPool
错误:Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/pool/impl ...
- Spring + Tomcat 启动报错java.lang.ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool
错误如下: -- ::,-[TS] INFO http-- org.springframework.beans.factory.support.DefaultListableBeanFactory - ...
- org/apache/commons/pool/impl/GenericObjectPool异常的解决办法
org/apache/commons/pool/impl/GenericObjectPool异常的解决办法 webwork+spring+hibernate框架的集成, 一启动Tomcat服务器就出了 ...
- 对象池化技术 org.apache.commons.pool
恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率.Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以 ...
- apache commons pool
apache commons下的pool 其中的borrowObject函数源代码显示其产生可用对象的过程: 如果stack中有空闲的对象,则pop对象,激活对象(activate函数),验证对象(v ...
- Apache Commons Pool 故事一则
Apache Commons Pool 故事一则 最近工作中遇到一个由于对commons-pool的使用不当而引发的问题,习得正确的使用姿势后,写下这个简单的故事,帮助理解Apache Commons ...
- 池化 - Apache Commons Pool
对于那些创建耗时较长,或者资源占用较多的对象,比如网络连接,线程之类的资源,通常使用池化来管理这些对象,从而达到提高性能的目的.比如数据库连接池(c3p0, dbcp), java的线程池 Execu ...
- JedisCluster中应用的Apache Commons Pool对象池技术
对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分. apache common pool 官方文档可以参考:https://c ...
- Cache Lucene IndexReader with Apache Commons Pool
IndexReaderFactory.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 2 ...
随机推荐
- linux(本机)配置域名
hosts是一个没有扩展名的系统文件, 其作用就是将主机名映射到对应的ip地址. 当用户执行一条ping命令时(如ping www.abc.com),系统会首先自动从hosts文件中寻找www.abc ...
- 【bzoj2038】 小Z的袜子(hose)
http://www.lydsy.com/JudgeOnline/problem.php?id=2038 (题目链接) 转自:http://blog.csdn.net/bossup/article/d ...
- 恶意软件/BOT/C2隐蔽上线方式研究
catalogue . 传统木马上线方式 . 新型木马上线方式 . QQ昵称上线 . QQ空间资料上线 . 第三方域名上线 . UDP/TCP二阶段混合上线 . Gmail CNC . NetBot两 ...
- DLUTOJ1216
题目大意是:给出N个正整数,其中至多有一个数只出现一次,其余的数都出现了两次.判断是否有某个数只出现一次,若有输出这个数,否则输出“-1”. 1<=N<=5000000 这道题的正解是用位 ...
- AngularJs ngReadonly、ngSelected、ngDisabled
ngReadonly 该指令将input,textarea等文本输入设置为只读. HTML规范不允许浏览器保存类似readonly的布尔值属性.如果我们将一个Angular的插入值表达式转换为这样的属 ...
- plist文件的使用
什么是plist文件 直接将数据写在代码里面,不是一种合理的做法.如果经常改,就要经常翻开对应的代码进行修改,造成代码扩展性低 因此,可以考虑将经常变的数据放在文件中进行存储,程序启动后从文件中读取最 ...
- 数据结构与算法分析–Minimum Spanning Tree(最小生成树)
给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...
- Python: sort,sorted,OrderedDict的用法
Python: sort,sorted,OrderedDict的用法 from http://stqdd.com/archives/427 by 莫亚菜 python对容器内数据的排序有两种,一种是容 ...
- DNS介绍
DNS出现及演化 网络出现的早期 是使用IP地址通讯的,那时就几台主机通讯.但是随着接入网络主机的增多,这种数字标识的地址非常不便于记忆,UNIX上就出现了建立一个叫做hosts的文件(Linux和w ...
- 在Nginx中部署基于IP的虚拟主机
一.虚拟主机概念 虚拟主机是在网络服务器上划分出一定的磁盘空间供用户放置站点.应用组件等,提供必要的站点功能.数据存放和传输功能.所谓虚拟主机,也叫"网站空间", 就是把一台运行在 ...