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下安装与使用本地的perl模块
转自 http://www.cnblogs.com/xianghang123/archive/2012/08/23/2652806.html Linux下安装与使用本地的perl模块 在使用Linux ...
- 解决不能访问远程mysql的问题
一般是没有给用户访问权限 给用户test_user授权,让他可以从外部登陆和本地登陆注意:@左边是用户名,右边是域名.IP和%,表示可以访问mysql的域名和IP,%表示外部任何地址都能访问. m ...
- 精通Web Analytics 2.0 (2) 内容简介
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 这本书里有什么? 这本书是在我第一本书<网站分析:每天一小时>的基础上创作的.我并不打算绕弯子,第一章是网站分析2. ...
- 77.Android之代码混淆
转载:http://www.jianshu.com/p/7436a1a32891 简介 作为Android开发者,如果你不想开源你的应用,那么在应用发布前,就需要对代码进行混淆处理,从而让我们代码即使 ...
- ——YC,你学到了吗?——学到了学到了
又是周末了,想着开始我的每周一切(每周做一次从切图到静态网页布局的练习)任务吧,无意间看了看别人的页面,发现--我去,这个动画挺有意思的啊,怎么实现的?然后翻代码+搜索,啊,原来是插件啊~给我的也用上 ...
- Android成长日记-使用Intent实现页面跳转
Intent:可以理解为信使(意图),由Intent来协助完成Android各个组件之间的通讯 Intent实现页面之间的跳转 1->startActivity(intent) 2->st ...
- 洛谷P1168 中位数
题目描述 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[2], …, A[2k - 1]的中位数.[color=red]即[/color] ...
- poj3484 Showstopper 二分
题目地址 二分用的很是巧妙!关键是抽象出问题本质. #include <cstdio> #include <string> #include <cstring> ; ...
- ObjC 利用反射和KVC实现嵌套对象序列化成JSON数据
原理: 0.创建一个新的可变字典:NSMutableDictionary 1.采用class_copyPropertyList函数遍历对象的属性 2.property_getName获取属性名,val ...
- RabbitMQctl命令
RabbitMQControl RabbitMQ提供了可视化的网页供我们进行一些配置与操作,但是ctl的命令比UI来的专业的多,一些UI无法完成的操作就需要使用ctl命令来进行处理了 这里是官方的文档 ...