用commons-pool可以管理一些数据库连接池等东西,也可以结合动态代理实现自己的一些共有业务。
maven依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
MyBean测试对象,对象池存管理该对象:
package littlehow.commons.demo.pool;
import java.sql.Timestamp;
/**
* MyBean
*
* @author littlehow
* @time 2016-05-27 11:11
*/
public class MyBean {
public static final String[] names = {"Littlehow", "Jim Green", "Black Tom", "White Cat", "Yellow Dog", "Color Wolf"};
/**
* bean被初始化的时间
*/
private long instanceTime = System.currentTimeMillis();
/**
* 名称
*/
private String name;
/**
* 对象是否存活
*/
private boolean live = true;
/**
* 实例化对象
*/
public MyBean () {
this.name = names[(int)(this.instanceTime % names.length)];
}
/**
* name由调用方指定
* @param name
*/
public MyBean (String name) {
this.name = name;
}
/**
* 销毁方法
*/
public void beKilled () {
System.out.print("我[" + this.name + "]居然被销毁了,我不甘心啊,");
System.out.println("就活了[" + (System.currentTimeMillis() - this.instanceTime) +"]毫秒!");
}
public String toString () {
return "我[" + this.name + "]出生在:" + new Timestamp(this.instanceTime);
}
/**
* 获取实例化时间
* @return
*/
public long getInstanceTime () {
return this.instanceTime;
}
/**
* 获取对象标志
* @return
*/
public String getName () {
return this.name;
}
/**
* 死亡掉
*/
public void deadBean () {
this.live = false;
}
/**
* 人不是还活着
* @return
*/
public boolean isLive () {
return this.live;
}
/**
* 相当于打开一个链接对象,如果是管理数据库连接的话
*/
public void start () {
System.out.println(this.name + "的生命开始了");
}
}
KeyPoolFactory对象池工厂
package littlehow.commons.demo.pool;
import org.apache.commons.pool2.BaseKeyedPooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
/**
* KeyPoolFactory 带key的对象工厂
*
* @author littlehow
* @time 2016-05-27 11:28
*/
public class KeyPoolFactory {
/**
* 对象池
*/
private static GenericKeyedObjectPool<String, MyBean> pool;
/**
* 对象池的参数设置
*/
private static final GenericKeyedObjectPoolConfig config;
/**
* 对象池每个key最大实例化对象数
*/
private final static int TOTAL_PERKEY = 10;
/**
* 对象池每个key最大的闲置对象数
*/
private final static int IDLE_PERKEY = 3;
static {
config = new GenericKeyedObjectPoolConfig ();
config.setMaxTotalPerKey(TOTAL_PERKEY);
config.setMaxIdlePerKey(IDLE_PERKEY);
/** 支持jmx管理扩展 */
config.setJmxEnabled(true);
config.setJmxNamePrefix("myPoolProtocol");
/** 保证获取有效的池对象 */
config.setTestOnBorrow(true);
config.setTestOnReturn(true);
}
/**
* 从对象池中获取对象
* @param key
* @return
* @throws Exception
*/
public static MyBean getBean (String key) throws Exception {
if (pool == null) {
init();
}
return pool.borrowObject(key);
}
/**
* 归还对象
* @param key
* @param bean
*/
public static void returnBean (String key, MyBean bean) {
if (pool == null) {
init();
}
pool.returnObject(key , bean);
}
/**
* 关闭对象池
*/
public synchronized static void close () {
if (pool !=null && !pool.isClosed()) {
pool.close();
pool = null;
}
}
/**
* 初始化对象池
*/
private synchronized static void init () {
if (pool != null) return;
pool = new GenericKeyedObjectPool<String, MyBean>(new MyBeanPooledFactory(), config);
}
/**
* 对象工厂
*/
static class MyBeanPooledFactory extends BaseKeyedPooledObjectFactory<String, MyBean> {
/**
* 创建对象
* @param key
* @return
* @throws Exception
*/
public MyBean create(String key) throws Exception {
MyBean myBean = new MyBean();
myBean.start();
System.out.println(myBean);
return myBean;
}
public PooledObject<MyBean> wrap(MyBean value) {
return new DefaultPooledObject<MyBean>(value);
}
/**
* 验证对象是否有效
* @param key
* @param p
* @return
*/
public boolean validateObject(String key, PooledObject<MyBean> p) {
MyBean bean = p.getObject();
if(!bean.isLive()){
System.out.println(bean.getName() + "已经死了,无法唤醒他了!");
return false;
}
return true;
}
/**
* 销毁
* @param key
* @param p
* @throws Exception
*/
public void destroyObject(String key, PooledObject<MyBean> p)
throws Exception {
/** 杀死他 */
p.getObject().beKilled();
}
public void activateObject(String key, PooledObject<MyBean> p)
throws Exception {
super.activateObject(key, p);
}
public void passivateObject(String key, PooledObject<MyBean> p)
throws Exception {
super.passivateObject(key, p);
}
}
}
GetBean测试类
package littlehow.commons.demo.pool;
import org.junit.Test;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
/**
* GetBean 测试从对象池中获取对象
*
* @author littlehow
* @time 2016-05-27 14:03
*/
public class GetBean {
static String[] keys = {"2016052700", "2016052800", "2016052900"};
/** 随机key */
Random r = new Random();
/**
* 获取key值
* @return
*/
String getKey () {
return keys[r.nextInt(keys.length)];
}
/**
* 获取对象
*/
@Test
public void getBean () {
String key = getKey();
/** 保证key值长度为10 */
assertTrue( "key的长度必须为10", key != null && key.length() == 10 );
try {
/**
* 同一个key最多可以获取10个对象
* 可以看出,当获取10个对象时,对象池就再也不能给出对象了
*/
for (int i = 0; i < 20; i ++) {
TimeUnit.SECONDS.sleep(1);//睡一秒
KeyPoolFactory.getBean(key);
}
/** 可以看出拿对象时阻塞的 */
System.out.println("前方是否阻塞到我了...");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取对象再还回去
*/
@Test
public void getAndReturnBean () {
String key = getKey();
/** 保证key值长度为10 */
assertTrue( "key的长度必须为10", key != null && key.length() == 10 );
try {
/**
* 同一个key最多可以获取10个对象
* 可以看出,当获取10个对象时,对象池就再也不能给出对象了
*/
for (int i = 0; i < 20; i ++) {
TimeUnit.SECONDS.sleep(1);//睡一秒
MyBean my = KeyPoolFactory.getBean(key);
/** 让对象死掉 */
my.deadBean();
/** 归还对象
* 因为执行了my.deadBean(),这时候在归还对象时,他发现对象已经
* 不合法了,这时候工厂就会重新拿对象
* 如果屏蔽掉my.deadBean()这样的方法,那么获取到的对象将是第一次获取到的对象
*/
KeyPoolFactory.returnBean(key, my);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 多个key同时去获取bean
*/
@Test
public void getBeans () {
String key1 = getKey();
String key2 = key1;
while (key1.equals(key2)) {
key2 = getKey();
}
assertTrue( "key的长度必须为10,而获取到的key1="+key1, key1 != null && key1.length() == 10 );
assertTrue( "key的长度必须为10,而获取到的key2="+key2, key2 != null && key2.length() == 10 );
try {
/**
* 同一个key最多可以获取10个对象
* 20个对象用2个key就可以全部输出
* 这些都是不归还的
*/
for (int i = 0; i < 20; i ++) {
TimeUnit.SECONDS.sleep(1);//睡一秒
if (i % 2 == 0){
KeyPoolFactory.getBean(key1);
} else {
KeyPoolFactory.getBean(key2);
}
}
/**
* 可以看出这句输出了
*/
System.out.println("前方是否阻塞到我了...");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 一个线程借对象,一个线程还对象
* 如果获取和归还的时间差特别大,会导致某些时候线程阻塞,因为对象已经拿完了
* 就好像借书一样,如果书被借完了,那么再想借就得需要等借书人还书了。
*/
volatile boolean dead = false;//死亡对象标志
@Test
public void getAndReturnByThread () {
/** 对象缓存 */
final ConcurrentHashMap<String, LinkedBlockingDeque<MyBean>> beans = new ConcurrentHashMap<String, LinkedBlockingDeque<MyBean>>();
/**
* 借对象,每秒借一个
*/
new Thread("borrow") {
public void run(){
while (true) {
String key = getKey();
LinkedBlockingDeque<MyBean> link = beans.get(key);
if (link == null) {
/** 最多存放10个对象 */
link = new LinkedBlockingDeque<MyBean>(10);
beans.put(key, link);
}
try {
MyBean bean = KeyPoolFactory.getBean(key);
link.push(bean);
System.out.println(Thread.currentThread().getName() + "操作:key=" + key + ",bean=" + bean);
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}.start();
/**
* 还对象,每3秒还一个
*/
new Thread("return") {
public void run () {
while (true) {
String key = getKey();
LinkedBlockingDeque<MyBean> link = beans.get(key);
if (link == null || link.size() == 0) continue;
/** 弹出元素 */
MyBean bean = link.pop();
if (dead) {
bean.deadBean();
dead = false;
}
System.out.println(Thread.currentThread().getName() + "操作:key="+key + ",bean="+bean);
KeyPoolFactory.returnBean(key, bean);
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
/**
* 每5秒死亡一对象
*/
new Thread("dead") {
public void run () {
while (true) {
try {
TimeUnit.SECONDS.sleep(5);
dead = true;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
try {
TimeUnit.MINUTES.sleep(5);//5分钟后结束程序
Runtime.getRuntime().exit(0);
} catch (Exception e) {
}
}
}