我们在服务器开发的过程中,往往会有一些对象,它的创建和初始化需要的时间比较长,比如数据库连接,网络IO,大数据对象等。在大量使用这些对象时,如果不采用一些技术优化,就会造成一些不可忽略的性能影响。一种办法就是使用对象池,每次创建的对象并不实际销毁,而是缓存在对象池中,下次使用的时候,不用再重新创建,直接从对象池的缓存中取即可。为了避免重新造轮子,我们可以使用优秀的开源对象池化组件apache-common-pool2,它对对象池化操作进行了很好的封装,我们只需要根据自己的业务需求重写或实现部分接口即可,使用它可以快速的创建一个方便,简单,强大对象连接池管理类。

一,common-pool2简介

首先是下载这个组件,使用maven引入下面依赖即可:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-pool2</artifactId>

<version>2.4.2</version>

</dependency>

Common-pool2中的代码不是太多,有几个种要的接口和实现类,common-pool2使用的是面向接口的编程,它为我们提供的是一个抽象的对象池管理方式,所以根据我们业务的不同,我们需要重写或实现一些方法和接口,我们一个一个看一下。

1,GenericObjectPool

这个是对象池实现的核心类,它实现了对对象池的管理,是一个基本的对象池实现,一般情况下,我们可以直接使用。在使用这个类的时候,我们需要传入两个重要的参数:GenericObjectPoolConfig类和PooledObjectFactory接口的实现,一会我们再详细说这两个。

在GenericObjectPool中,有两个我们会用到的方法:

public T borrowObject() throws Exception 从对象池中获取一个对象

public void returnObject(T obj) 对象使用完之后,归还到对象池,

其它还有一些方法,比如关闭对象池,销毁对象池,获取对象池中空闲的对象个数等,可以自行查看API。

2,PooledObjectFactory接口

这个接口是我们要实现的,它对要实现对象池化的对象做了一些管理。这个工厂接口就是为了让我们根据自己的业务创建和管理要对象池化的对象。

PooledObject<T>  makeObject() throws Exception;

这个方法是用来创建一个对象,当在GenericObjectPool类中调用borrowObject方法时,如果当前对象池中没有空闲的对象,GenericObjectPool会调用这个方法,创建一个对象,并把这个对象封装到PooledObject类中,并交给对象池管理。

void destroyObject(PooledObject<T> p) throws Exception;

销毁对象,当对象池检测到某个对象的空闲时间(idle)超时,或使用完对象归还到对象池之前被检测到对象已经无效时,就会调用这个方法销毁对象。对象的销毁一般和业务相关,但必须明确的是,当调用这个方法之后,对象的生命周期必须结果。如果是对象是线程,线程必须已结束,如果是socket,socket必须已close,如果是文件操作,文件数据必须已flush,且文件正常关闭。

boolean validateObject(PooledObject<T> p);

检测一个对象是否有效。在对象池中的对象必须是有效的,这个有效的概念是,从对象池中拿出的对象是可用的。比如,如果是socket,那么必须保证socket是连接可用的。在从对象池获取对象或归还对象到对象池时,会调用这个方法,判断对象是否有效,如果无效就会销毁。

void activateObject(PooledObject<T> p) throws Exception;

激活一个对象或者说启动对象的某些操作。比如,如果对象是socket,如果socket没有连接,或意外断开了,可以在这里启动socket的连接。它会在检测空闲对象的时候,如果设置了测试空闲对象是否可以用,就会调用这个方法,在borrowObject的时候也会调用。另外,如果对象是一个包含参数的对象,可以在这里进行初始化。让使用者感觉这是一个新创建的对象一样。

void passivateObject(PooledObject<T> p) throws Exception;

钝化一个对象。在向对象池归还一个对象是会调用这个方法。这里可以对对象做一些清理操作。比如清理掉过期的数据,下次获得对象时,不受旧数据的影响。

一般来说activateObject和passivateObject是成对出现的。前者是在对象从对象池取出时做一些操作,后者是在对象归还到对象池做一些操作,可以根据自己的业务需要进行取舍。

3,带Key的对象池GenericKeyedObjectPool

这种对象池和前面的GenericObjectPool对象池操作是一样的,不同的是对应的每个方法带一个key参数。你可以把这个GenericKeyedObjectPool的对象池看作是一个map的GenericObjectPool,每个key对应一个GenericObjectPool。它用于区别不同类型的对象。比如数据库连接,有可能会连接到不同地址的数据库上面。就可以用这个区分。

4,参数配置类GenericObjectPoolConfig

这个类允许使用者对对象池的一些参数进行调整,根据需要定制对象池。下面说逐一说一下每个参数的含义。

lifo :对象池存储空闲对象是使用的LinkedBlockingDeque,它本质上是一个支持FIFO和FILO的双向的队列,common-pool2中的LinkedBlockingDeque不是Java原生的队列,而有common-pool2重新写的一个双向队列。如果为true,表示使用FIFO获取对象。默认值是true.建议使用默认值。

fairness:common-pool2实现的LinkedBlockingDeque双向阻塞队列使用的是Lock锁。这个参数就是表示在实例化一个LinkedBlockingDeque时,是否使用lock的公平锁。默认值是false,建议使用默认值。

maxWaitMillis:当没有空闲连接时,获取一个对象的最大等待时间。如果这个值小于0,则永不超时,一直等待,直到有空闲对象到来。如果大于0,则等待maxWaitMillis长时间,如果没有空闲对象,将抛出NoSuchElementException异常。默认值是-1;可以根据需要自己调整,单位是毫秒。

minEvictableIdleTimeMillis:对象最小的空闲时间。如果为小于等于0,最Long的最大值,如果大于0,当空闲的时间大于这个值时,执行移除这个对象操作。默认值是1000L * 60L * 30L;即30分钟。这个参数是强制性的,只要空闲时间超过这个值,就会移除。

softMinEvictableIdleTimeMillis:对象最小的空间时间,如果小于等于0,取Long的最大值,如果大于0,当对象的空闲时间超过这个值,并且当前空闲对象的数量大于最小空闲数量(minIdle)时,执行移除操作。这个和上面的minEvictableIdleTimeMillis的区别是,它会保留最小的空闲对象数量。而上面的不会,是强制性移除的。默认值是-1;

numTestsPerEvictionRun:检测空闲对象线程每次检测的空闲对象的数量。默认值是3;如果这个值小于0,则每次检测的空闲对象数量等于当前空闲对象数量除以这个值的绝对值,并对结果向上取整。

testOnCreate:在创建对象时检测对象是否有效,true是,默认值是false。

testOnBorrow:在从对象池获取对象时是否检测对象有效,true是;默认值是false。

testOnReturn:在向对象池中归还对象时是否检测对象有效,true是,默认值是false。

testWhileIdle:在检测空闲对象线程检测到对象不需要移除时,是否检测对象的有效性。true是,默认值是false。

timeBetweenEvictionRunsMillis:空闲对象检测线程的执行周期,即多长时候执行一次空闲对象检测。单位是毫秒数。如果小于等于0,则不执行检测线程。默认值是-1;

blockWhenExhausted:当对象池没有空闲对象时,新的获取对象的请求是否阻塞。true阻塞。默认值是true;

maxTotal:对象池中管理的最多对象个数。默认值是8。

maxIdle:对象池中最大的空闲对象个数。默认值是8。

minIdle:对象池中最小的空闲对象个数。默认值是0。

以上就是common-pool2对象池的配置参数,使用的时候可以根据自己的需要进行调整。

5,common-pool2的应用

使用common-pool2的对象池技术的一个完美例子就是redis的Java客户端JedisPool。大家可以下载Jedis的包,查看源码进行学习。下次我将分享一个我使用common-pool2实现的一个thrift客户端调用的连接池实现。

综上所述,使用common-pool2可以快速的创建一个安全,强大,简单的对象池管理类。它的开源性使它的功能得到了众多项目的检测,是非常安全的。在我们的业务中,如果有需要使用对象池化的操作,可以使用common-pool2快速实现。

转载请注明来自游戏技术网:http://www.youxijishu.com

common-pool2对象池(连接池)的介绍及使用的更多相关文章

  1. (转)websphere线程池 连接池设置

    原文:http://www.talkwithtrend.com/Article/207511 池(Pool)是WebSphere中最常涉及的概念之一.从网络.Web 服务器.Web 容器.EJB 容器 ...

  2. Apache common pool2 对象池

    对象池的容器:包含一个指定数量的对象.从池中取出一个对象时,它就不存在池中,直到它被放回.在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触 ...

  3. 线程池-连接池-JDBC实例-JDBC连接池技术

    线程池和连接池   线程池的原理:     来看一下线程池究竟是怎么一回事?其实线程池的原理很简单,类似于操作系统中的缓冲区的概念,它的流程如下:先启动若干数量的线程,并让这些线程都处于睡眠状态,当客 ...

  4. MySQL 线程池&连接池&长连接&短连接

    线程池 简介 1.mysql每连接每线程,mysql都分配一个单独的线程,该线程处理客户端发来的所有命令 2.每个线程会占用一定的系统资源,线程数越多消耗的系统资源也越多 3.线程的创建和销毁有一定的 ...

  5. mybatis深入之动态查询和连接池介绍

    mybatis深入之动态查询和连接池介绍 一.mybatis条件查询 在mybatis前述案例中,我们的查询条件都是确定的.但在实际使用的时候,我们的查询条件有可能是动态变化的.例如,查询参数为一个u ...

  6. day18 14.连接池介绍

    数据源在软件编程行业有两种概念:一种数据源指的是存储数据的源头(数据库啊文件啊叫数据源),一种指的是连接池(连接池的英文单词叫做DataSource,直译就是数据源).数据源可以指数据库,也可以指连接 ...

  7. Java基础学习笔记二十七 DBUtils和连接池

    DBUtils 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组件一个成员:DBUtils.DBUtils就是JDBC的简化开发 ...

  8. DBUtils和连接池

    今日内容介绍 1.DBUtils 2.连接池 ###01DButils工具类的介绍个三个核心类 * A: DButils工具类的介绍个三个核心类 * a: 概述 * DBUtils是java编程中的数 ...

  9. 使用commons-pool2实现FTP连接池

    ​ GitHub : https://github.com/jayknoxqu/ftp-pool 一. 连接池概述 ​ 频繁的建立和关闭连接,会极大的降低系统的性能,而连接池会在初始化的时候会创建一定 ...

随机推荐

  1. ActiveReports 报表应用教程 (7)---交叉报表及数据透视图实现方案

    在 ActiveReports 中可以通过矩阵控件非常方便的实现交叉报表,同时还可以设置数据的分组.排序.过滤.小计.合计等操作,可以满足您报表的智能数据分析等需求.在矩阵控件中组的行数和列数由每个行 ...

  2. Go eclipse plugin

    Installation Requirements: Eclipse 4.5 (Mars) or later. Java VM version 8 or later. Gocode and Go or ...

  3. RCA端子颜色(红、白、黄)

    RCA端子(红白黄)的作用: 黄:视频 红:左声道 白:右声道 RCA为两口插头,红色代表左声道,白色为右声道,3.5(AUX口)同样为立体声接头,虽然它只有一个端口,同样也具有左右声道分开传输的功能 ...

  4. TeamCity配置笔记

    1.编译sln 2.发布网站 3.重复代码检测 4.代码分析 5.单元测试&覆盖率测试 查看代码覆盖率 7.代码签入时自动触发编译 8.通知 1.在teamcity安装目录中找到TrayNot ...

  5. javascript获取url信息的常见方法

    先以"http://www.cnblogs.com/wuxibolgs329/p/6188619.html#flag?test=12345"为例,然后获得它的各个组成部分. 1.获 ...

  6. COMMIT WORK AND WAIT 是在WAIT什么

    wait 还是不wait,这是个问题.       这是同步更新还是异步更新的问题:如果是只commit work,是异步更新,触发注册在当前SAP LUW中所有数据更新动作,数据更新动作由SAP的更 ...

  7. Hosts文件小结

    今天又遇到Hosts,小结一下: Hosts文件是什么? Hosts文件从表象上来看是一个没有扩展名的系统文件.其基本作用就是将一些常用的网址域名与其对应的IP地址建立一个关联"数据库&qu ...

  8. iOS— UIScrollView和 UIPageControl之间的那些事

    本代码主要实现在固定的位置滑动图片可以切换. 目录图如下: ViewController.h #import <UIKit/UIKit.h> // 通过宏定义定义宽和高 #define W ...

  9. iOS 利用长按手势移动 Table View Cells

    本文译自:Cookbook: Moving Table View Cells with a Long Press Gesture 目录: 你需要什么? 如何做? 如何将其利用至UICollection ...

  10. Java眼中的XML--文件读取--2 应用SAX方式解析XML

    1.获取一个SAXParserFactory的实例.2.通过factory获取SAXParser实例.  3.新建一个包和继承自DefaultHandler的类.  因为SAX遍历方式,比如便利一个节 ...