一个Connection类,能够想象成一个远程链接好比数据库链接等。其中包括建立链接,关闭链接,和一个print方法。
java
[java] view plaincopyprint?数据库
package com.googlecode.garbagecan.commons.pool.sample3; apache
import org.slf4j.Logger; 测试
import org.slf4j.LoggerFactory; this
public class MyConnection { google
private static Logger logger = LoggerFactory.getLogger(MyConnection.class); spa
private String name; .net
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方法。
[java] view plaincopyprint?
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);
}
}
一个测试类
[java] view plaincopyprint?
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类仍是有不少配置参数的,这里只是列出的最简单的几个经常使用的,具体能够参考官方文档。