Apache Common-pool2对象池分析和应用
Apache Common-pool2包提供了一个通用的对象池技术的实现。可以很方便的基于它来实现自己的对象池,比如DBCP和Jedis他们的内部对象池的实现就是依赖于Common-pool2。
对象的创建和销毁在一定程度上会消耗系统的资源,虽然jvm的性能在近几年已经得到了很大的提高,对于多数对象来说,没有必要利用对象池技术来进行对象的创建和管理。但是对于有些对象来说,其创建的代价还是比较昂贵的,比如线程、tcp连接、数据库连接等对象,因此对象池技术还是有其存在的意义。
实现分析
Common-pool2由三大模块组成:ObjectPool、PooledObject和PooledObjectFactory。
ObjectPool:提供所有对象的存取管理。
PooledObject:池化的对象,是对对象的一个包装,加上了对象的一些其他信息,包括对象的状态(已用、空闲),对象的创建时间等。
PooledObjectFactory:工厂类,负责池化对象的创建,对象的初始化,对象状态的销毁和对象状态的验证。
ObjectPool会持有PooledObjectFactory,将具体的对象的创建、初始化、销毁等任务交给它处理,其操作对象是PooledObject,即具体的Object的包装类。
org.apache.commons.pool2.impl 包提供了一个默认的对象池实现。
主要还是这三个模块的实现,其中PooledObjectFactory在包里没有具体实现,因为这涉及到具体对象的创建,需要应用本身去实现,这也体现了设计上的解耦合性。
BaseGenericObjectPool
它主要定义了对象池的一些配置信息和实现jmx注册注销等功能。
以下是对象池的相关配置
GenericObjectPool
数据结构:ConcurrentHashMap和LinkedBlockingDeque。前者用于存储所有的对象(不含销毁的对象),后者用于存储空闲的对象。
borrowObject()大体思路如下
1 从LinkedBlockingDeque中pollFirst
2 若为空,检查对象池对象是否达到上限,若是重复1,若否,则调用PooledObjectFactory的makeObject去创建一个对象
3 得到对象之后,对对象进行初始化和一些配置的计数处理,同时将对象加入到ConcurrentHashMap。
returnObject(T obj)大体思路如下
1 根据obj从ConcurrentHashMap拿到其对应的PooledObject p
2 判空;将p状态置为RETURN
3 若getTestOnReturn参数为true,进行validateObject
4 对p进行passivateObject,与初始化相反
5 更新p状态为IDLE
6 归还Pool:Pool的idle实例达到上限或者Pool已经关闭,销毁之,否则将p加入到LinkedBlockingDeque中。
DefaultPooledObject
默认的PooledObject实现,维护池化对象的一系列状态参数。
简介
在以往的一些工作中总接触到一个池的概念。这些池包括有线程池,对象池和连接池等。从池本身的概念来说,它是将一系列的资源事先准备好放在一个地方,等需要的时候直接拿过去用。而用完之后再放回来。和我们平常的需要使用资源再创建的方式相比,这种池的方式节省了创建和销毁资源的这么一个过程。所以说,对于一些比较比较稀缺的资源或者创建和销毁影响系统性能的资源,采用池的方式可以有效的提高整体性能。最近一段时间正好要用到一些数据库连接池等东西,趁这个时机把一些相关的部分好好的学习总结一下。如前面提到的,我们使用到的典型的线程池有jdk里的ExecutorService相关的一系列工具类(在这篇文章里有阐述),而一些典型的数据库连接池有cp03和dbcp。最近用到了dbcp,而它主要是基于commons-pool实现的,所以我们先从commons-pool2开始吧。
整体结构分析
在正式分析commons-pool2的结构开始,我们设想一下,如果我们自己来设计一个object pool的话,我们该怎么来做呢? 首先一个,我们从直接使用的角度来说,肯定需要一个ObjectPool对象,它负责保存我们需要访问的对象,我们把这个对象用完之后就返还给它。更细化一点的考虑的话,我们在使用前需要根据配置事先创建一些对象,后面需要使用的时候直接取就可以了。然后我们需要能够知道pool里面有多少可以用的对象。还有一个就是对象在被使用前是一个类似于初始化的状态,而使用完之后可能是另外的一个状态,既然我们希望对象能够被复用,在返回到pool里的时候可能还需要做一些重置的工作。 除了这些以外,如果我们考虑对象的创建。我们可以将创建对象的职责给pool,这样pool同时既要管理对象的存取和回收又要管对象的创建和状态设置等。这有点像一个图书馆的管理员,他既要管借还书,还要管怎么造纸印书。这样想来,似乎管的职责有点多了。我们也可以将对象的创建单独分离处理作为一个factory来做。 其实,通过前面的这些讨论,我们几乎也能创建一个像模像样的pool。如果结合commons-pool2的详细设计,我们会发现它的设计思路和我们也是基本上一致的。它主要由3个大的部分组成: ObjectPool:专门实现对象存取和状态管理的池实现。我们直接操作的线程池就是定义在这里。值得注意的一点是这里定义的只是怎么来获取以及释放对象等操作,至于具体对象是怎么创建的,一般都通过独立的一个PooledObjectFactory来操心了。 PooledObject:这是commons-pools里比较有意思的一个类族。是对需要放到池里对象的一个包装类。添加了一些附加的信息,比如说状态信息,创建时间,激活时间,关闭时间等。这些添加的信息方便pool来管理和实现一些特定的操作。 PooledObjectFactory: 如我们前面所讨论的,管理具体对象的状态,比如创建,初始化,验证对象状态和销毁对象。 通过我们的这些讨论,他们这三者就构成了一个object pool的基本框架。他们的关系可以用如下的一个图来描述: 用一句话来概括他们整体的关系就是factory创建需要放入pool的对象,经过PooledObject包装一下就可以上架了。 有一个地方需要注意一下,虽然我们这里将它划分成3个主要的部分,从更精确的细节来看,每一个类族里都有一些不同的实现,这里我们再针对每一类族做一个大体的介绍。 ObjectPool类族 ObjectPool类族包含了以ObjectPool为代表的一系列pool,其中最主要的两类就是ObjectPool和KeyedObjectPool,他们分别针对普通的pool和以名值对映射的pool。和他们相关的整体几个类结构如下图:
从前面的图里头我们可以看到,真正定义的接口就是ObjectPool和KeyedObjectPool,具体的实现里有GenericObjectPool, GenericKeyedObjectPool和SoftReferenceObjectPool。不管是哪一种他们都引用了PooledObject。 这里我们不详细分析具体实现的代码,我们先就前面的设想来验证一下他们的整体思路。既然是ObjectPool,那它就应该管borrowObject, returnObject之类的了。是不是呢?我们先看看ObjectPool这一块的代码:
public interface ObjectPool<t> {
T borrowObject() throws Exception, NoSuchElementException,
IllegalStateException;
void returnObject(T obj) throws Exception;
void invalidateObject(T obj) throws Exception;
void addObject() throws Exception, IllegalStateException,
UnsupportedOperationException;
int getNumIdle();
int getNumActive();
void clear() throws Exception, UnsupportedOperationException;
void close();
}
这部分的代码很简单直接,主要就是包含了一个pool需要的基本操作功能,比如从pool里取对象的borrowObject,返回对象到pool里的returnObject,还有一些查找里面可用对象数量以及管理pool的方法。这里的clear方法是用来清空里面处于idle状态的对象,而close方法则用来关闭整个pool。他们两者的一个典型差别就是clear之后里面没有可以用的对象了,我们需要再创建一些对象放进去。而close之后则连pool都访问不了了。 与ObjectPool对象的一个是KeyedObjectPool,它的操作方法基本上和ObjectPool一样,唯一的差别是它是基于key来操作的,所以所有相关的borrowObject, returnObject等操作都要提供key参数。 PooledObject类族 如前所述,PooledObject主要是对需要被加入到pool里的对象提供一个包装,方便来查看或者统计一些对象信息,比如某个对象创建的时间,空闲时间以及活跃时间等。下面是PooledObject相关
的类关系图:
既然是一个简单的包装,我们就来看看具体需要访问的一些方法。如下是PooledObject里的基本方法定义:
public interface PooledObject<t> extends Comparable<pooledobject<t>> {
T getObject();
long getCreateTime();
long getActiveTimeMillis();
long getIdleTimeMillis();
long getLastBorrowTime();
long getLastReturnTime();
long getLastUsedTime();
@Override
int compareTo(PooledObject<t> other);
@Override
boolean equals(Object obj);
@Override
int hashCode();
@Override
String toString();
boolean startEvictionTest();
boolean endEvictionTest(Deque<pooledobject<t>> idleQueue);
boolean allocate();
boolean deallocate();
void invalidate();
void setLogAbandoned(boolean logAbandoned);
void use();
void printStackTrace(PrintWriter writer);
PooledObjectState getState();
void markAbandoned();
void markReturning();
}
这里列出的一大堆方法其实就是标注了各种操作,很多都是PooledObject本身实现加上去的。ok,有了前面这些管理对象和包装对象的东西,我们再来看看具体制造和销毁对象的部分。 PooledObjectFactory 在commons-pool2里,我们专门抽象出来一个创建和销毁对象的接口,PooledObjectFactory。而具体对象的创建则由用户自定义实现。在本身的源代码里只有一个简单的抽象类BasePooledObjectFactory实现。我们来看看这个接口定义的方法:
public interface PooledObjectFactory<t> {
PooledObject<t> makeObject() throws Exception;
void destroyObject(PooledObject<t> p) throws Exception;
boolean validateObject(PooledObject<t> p);
void activateObject(PooledObject<t> p) throws Exception;
void passivateObject(PooledObject<t> p) throws Exception;
}
makeObject和destroyObject则分别用于创建销毁对象,很简单。而validateObject用于在每次创建对象放入到pool里或者从pool里取对象出来的时候验证是否对象合法。至于activeObject和passivateObject比较有意思。在这里给对象定义了一系列的状态。这里的设计假定所有在pool里可以被立马拿出去用的对象是一个idle状态,在拿到之后要用activateObject方法来激活一下。而对象要返回给pool的时候则要用passivateObject方法将它钝化。 和ObjectPool相对应的,PooledObjectFactory也有一个相应的KeyedPooledObjectFactory,他们的区别也一样,一个是基于key来操作一个不是。 其他 除了我们前面列举出来的这3个部分,还有org.apache.commons.pool2.impl和org.apache.commons.pool2.proxy这两个包。他们分别定义了前面定义的pool的默认实现和基于代理的实现。在后续的文章里会针对每个部分的细节实现做一个分析。 总结 commons-pool2的整体结构并不复杂,可以将其划分为3个角色,一个管对象的进出口,一个管对象的包装,一个对象的创建。感觉好像一个产销结合的商业团体啊。有意思。
Apache Common-pool2对象池分析和应用的更多相关文章
- Apache common pool2 对象池
对象池的容器:包含一个指定数量的对象.从池中取出一个对象时,它就不存在池中,直到它被放回.在池中的对象有生命周期:创建,验证,销毁,对象池有助于更好地管理可用资源,防止JVM内部大量临时小对象,频繁触 ...
- apache common pool2原理与实战
完整源码,请帮我点个star哦! 原文地址为https://www.cnblogs.com/haixiang/p/14783955.html,转载请注明出处! 简介 对象池顾名思义就是存放对象的池,与 ...
- JedisCluster中应用的Apache Commons Pool对象池技术
对象池技术在服务器开发上应用广泛.在各种对象池的实现中,尤其以数据库的连接池最为明显,可以说是每个服务器必须实现的部分. apache common pool 官方文档可以参考:https://c ...
- commons.pool2 对象池的使用
commons.pool2 对象池的使用 ? 1 2 3 4 5 <dependency> <groupId>org.apache.commons</groupI ...
- Apache Commons-pool实现对象池(包括带key对象池)
Commons-pool是一个apache开源组织下的众多项目的一个.其被广泛地整合到众多需要对象池功能的项目中. 官网:http://commons.apache.org/proper/common ...
- Apache Commons Pool2 源码分析 | Apache Commons Pool2 Source Code Analysis
Apache Commons Pool实现了对象池的功能.定义了对象的生成.销毁.激活.钝化等操作及其状态转换,并提供几个默认的对象池实现.在讲述其实现原理前,先提一下其中有几个重要的对象: Pool ...
- Java中对象池的本质是什么?(实战分析版)
简介 对象池顾名思义就是存放对象的池,与我们常听到的线程池.数据库连接池.http连接池等一样,都是典型的池化设计思想. 对象池的优点就是可以集中管理池中对象,减少频繁创建和销毁长期使用的对象,从而提 ...
- Java网络与多线程系列之1:实现一个简单的对象池
前言 为什么要从对象池开始呢,先从一个网络IO操作的demo说起 比如下面这段代码,显而易见已经在代码中使用了一个固定大小的线程池,所以现在的重点在实现Runnble接口的匿名对象上,这个对象每次创建 ...
- 基于Apache组件,分析对象池原理
池塘里养:Object: 一.设计与原理 1.基础案例 首先看一个基于common-pool2对象池组件的应用案例,主要有工厂类.对象池.对象三个核心角色,以及池化对象的使用流程: import or ...
随机推荐
- PNG图片去除额外透明区域
bitmapdata.getColorBoundsRect(0xFF000000,0x00000000,false) http://www.cnblogs.com/shinings/archive/2 ...
- Hibernate Annotation笔记
(1)简介:在过去几年里,Hibernate不断发展,几乎成为Java数据库持久性的事实标准.它非常强大.灵活,而且具备了优异的性能.在本文中,我们将了解如何使用Java 5 注释来简化Hiberna ...
- ubuntu安装jdk遇到的问题:cannot execute binary file
安装完jdk,配置好环境变量出现如下状况: cannot execute binary file 问题原因: jdk的位数与ubuntu的系统位数不一致 jdk 64位 ubuntu 32位 然后通过 ...
- bean中集合属性的配置
在实际的开发中,有的bean中会有集合属性,如下: package com.sevenhu.domain; import java.util.List; /** * Created by hu on ...
- ZOJ 2112 Dynamic Rankings(主席树の动态kth)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...
- MVC Controller弹窗的几种方式
MVC3 Controller弹窗的几种方式 return Content("<script language='javascript' type='text/javascript ...
- AHB中split机制简介
完整的AHB协议:1)可以多个master,并且需要外加一个Arbiter,和write multiplexor.为了保证每一时刻只有一个master拥有访问权. 2)为了增强pipeline的能力, ...
- php文件上传参数设置
php默认的 上传文件大小是2M,要上传超过此大小的文件,需要设置php和apache的一些参数,具体参考如下: 1.file_uploads:是否允许通过HTTP上传文件的开关,默认为ON就是开 2 ...
- Azure Deploy
http://msdn.microsoft.com/en-us/library/dn408531.aspx https://www.windowsazure.com/en-us/documentati ...
- 【海岛帝国系列赛】No.4 海岛帝国:LYF的太空运输站
50212228海岛帝国:LYF的太空运输站 [试题描述] 最近,“购物券”WHT在“药师傅”帝国资源大会上提出了“SSTS”太空运输站计划.由于恐怖分子前些日子刚猖狂完,炸毁高楼无数,YSF不得不执 ...