commons-pool2中GenericKeyedObjectPool应用demo

用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) {

        }
    }
}

 

 

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值