zoukankan      html  css  js  c++  java
  • java对象池化技术

     

    https://blog.csdn.net/tiane5hao/article/details/85957840

    对于共享资源,有一个很著名的设计模式:资源池。该模式正是为了解决资源频繁分配、释放所造成的问题的。把该模式应用到数据库连接管理领域,就是建立一个数据库连接池,提供一套高效的连接分配、使用策略,最终目标是实现连接的高效、安全的复用。还有一类对象池大家可能不太了解,对于nio中有个堆外内存,netty的ByteBuf对象的实现就是一个可复用的对象池来提高性能。连接池大家平时听的多,使用也多,但是自己实现应该比较少。

    先写一个简单通用的对象池

    总共包含几个类,代码如下:
    ICommonPool : 定义通用池,借出对象和归还对象
    PoolFactory :对象工厂,负责创建和销毁对象
    PoolConfig : 对象池的配置(最大连接数和最小连接数)
    BaseCommonPool :对象池的主要基础实现

    // An highlighted block
    package test.pool;
    
    /**
     * 通用池接口定义
     * @param <T>
     */
    public interface ICommonPool<T> {
        /**
         * 租借对象
         */
        T borrowObject() throws Exception;
    
        /**
         * 返回对象池
         */
        void returnObject(T object) throws Exception;
    }
    
    

    package test.pool;

    
    /**
     * 负责创建、销毁对象
     * @param <T>
     */
    public interface PoolFactory<T> {
    
        /**
         * 创建对象
         * @return
         */
        T makeObject();
    
        /**
         * 销毁对象
         */
        void destroyObject();
    }
    
    package test.pool;
    
    /**
     * 对象池配置
     */
    public class PoolConfig {
    
        // 池中最大对象
        private int maxTotal = 8;
    	//初始化对象数
        private int minTotal = 0;
    
        public int getMaxTotal() {
            return maxTotal;
        }
    
        public void setMaxTotal(int maxTotal) {
            this.maxTotal = maxTotal;
        }
    
        public int getMinTotal() {
            return minTotal;
        }
    
        public void setMinTotal(int minTotal) {
            this.minTotal = minTotal;
        }
    }
    
    package test.pool;
    
    import java.util.concurrent.LinkedBlockingQueue;
    /**
     * 对象池的基础实现
     * 这里用阻塞队列来实现
     * @param <T>
     */
    public class BaseCommonPool<T> implements ICommonPool<T> {
    
        private LinkedBlockingQueue<T> pool;
    
        private PoolConfig poolConfig;
        private PoolFactory<T> poolFactory;
    
        public BaseCommonPool(PoolConfig poolConfig, PoolFactory<T> poolFactory){
            this.poolConfig = poolConfig;
            this.poolFactory = poolFactory;
            initCommonPool();
        }
    
        private void initCommonPool() {
        	//代表池的大小
            pool = new LinkedBlockingQueue<T>(poolConfig.getMaxTotal());
            while (poolConfig.getMinTotal() > pool.size()){
                T obj = poolFactory.makeObject();
                pool.offer(obj);
            }
        }
    
        /**
         * 租借对象
         */
        public T borrowObject() throws Exception{
        	//如果队列中对象为空,poll方法返回null,非阻塞(take方法阻塞)
            T obj = pool.poll();
            if(obj != null){
                return obj;
            }
            return poolFactory.makeObject();
        }
    
        /**
         * 返回对象池
         */
        public void returnObject(T object) throws Exception{
        	//offer方法非阻塞,如果队列满了,直接抛弃,返回false,与put方法的区别自行百度
            if(!pool.offer(object)){
                poolFactory.destroyObject();
            }
        }
    }
    

    通过上面的通用池实现jedis连接池

    实现类如下:
    MyRedisFactory : jedis的对象工厂
    MyRedisPool : jedis连接池

    jedis pom依赖

     <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.0</version>
      </dependency>
    
    package test.objectpool;
    
    import redis.clients.jedis.Jedis;
    import test.pool.PoolFactory;
    
    public class MyRedisFactory implements PoolFactory<Jedis> {
    
        public MyRedisFactory() {
        }
    
        public Jedis makeObject() {
            Jedis jedis = new Jedis("127.0.0.1",6379);
            jedis.connect();
            return jedis;
        }
    
        public void destroyObject(Jedis jedis) {
            if (jedis.isConnected()) {
                try {
                    try {
                        jedis.quit();
                    } catch (Exception var4) {
                        ;
                    }
    
                    jedis.disconnect();
                } catch (Exception var5) {
                    ;
                }
            }
        }
    
    }
    
    package test.objectpool;
    
    import redis.clients.jedis.Jedis;
    import test.pool.BaseCommonPool;
    import test.pool.PoolConfig;
    
    public class MyRedisPool extends BaseCommonPool<Jedis> {
    
        public MyRedisPool(PoolConfig config) {
            super( config, new MyRedisFactory());
        }
    }
    
    

    连接池测试

    下面是jedis连接池和非连接池的测试(单线程),对于多线程后续测试了再补上,测试执行1万次本地redis方法get耗时比对结果如下:
    线程池执行耗时1153 ms
    创建redis执行耗时5437 ms
    性能有着明显的提升

    package test.objectpool;
    
    import redis.clients.jedis.Jedis;
    import test.pool.PoolConfig;
    
    public class PoolTest {
    
        public static void main(String[] args) {
            PoolConfig poolConfig = new PoolConfig();
            poolConfig.setMaxTotal(8);
            poolConfig.setMinTotal(4);
            MyRedisPool myRedisPool = new MyRedisPool(poolConfig);
    
            //线程池执行
            long start = System.currentTimeMillis();
            for(int i = 0; i < 10000; i++){
                Jedis jedis = null;
                try {
                    jedis = myRedisPool.borrowObject();
                    String result = jedis.get("aaa");
    //                System.out.println(result);
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    myRedisPool.returnObject(jedis);
                }
            }
            System.out.println("线程池执行耗时" + (System.currentTimeMillis() - start));
    
            //创建redis执行
            start = System.currentTimeMillis();
            for(int i = 0; i < 10000; i++){
                Jedis jedis = null;
                try {
                    jedis = new Jedis("127.0.0.1", 6379);
                    String result = jedis.get("aaa");
    //               System.out.println(result);
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    jedis.close();
                }
            }
            System.out.println("创建redis执行耗时" + (System.currentTimeMillis() - start));
        }
    }
    

     

  • 相关阅读:
    BootStrap 模态框禁用空白处点击关闭
    【云计算】使用nsenter进入Docker容器进行调试
    【架构】Nginx如何设置X-Request-ID请求头,记录请求时间:毫秒?
    【架构】微服务系列文章
    【云计算】OpenStack项目全面介绍
    【云计算】CloudFoundry参考资料
    【云计算】OpenShift容器服务参考
    【Web】Django OAuth invalid_grant error
    【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读
    【云计算】OpenStack Horizon DashBoard定制化,完整实现前后台交互
  • 原文地址:https://www.cnblogs.com/shoshana-kong/p/11249320.html
Copyright © 2011-2022 走看看