- 浏览: 691666 次
- 性别:
- 来自: 北京
博客专栏
-
读金庸故事,品程序人生
浏览量:47234
文章分类
最新评论
-
hty881008:
LZ,你的json返回是怎么出来的,我的怎么是No messa ...
使用CXF暴露您的REST服务 -
jxFY:
赞
Apache的对象池化工具commons-pool -
wangyudong:
新版本的Wisdom RESTClient地址https:// ...
使用CXF暴露您的REST服务 -
wangyudong:
由CXF实现的微服务需要有比较好的工具去测试RESTful A ...
使用CXF暴露您的REST服务 -
spring_springdata:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
Maven3实战笔记01环境配置与使用入门
1. 前言
当我们的应用中创建一个十分最重量级的对象的时候,往往为了节省资源成本,使用单例模式,整个的应用中就只有一个对象供大家使用。这样是节省了不少资源,也是大多数应用的做法。不过如果遇到并发量十分大的情况下,并发访问的问题也就出现了。OK即使您不用加锁synchronized,利用ThreadLoacl进行安全变量的副本,但是维持变量副本的资源也是需要消耗资源的。而且对于一个重量级的对象的多个方法多个线程同时调用此对象的同一个局部变量,多个副本的维护实际上也是挺占用资源的。
2. 轻量级对象
当然不是说所有的对象都适合池化的。池化的对象是一个重量级对象,什么是重量级对象。回答这个问题先说说什么是轻量级对象。比如我们做Web系统的DAO(注意:这里绝对不包括EJB的EAO),就是为了调用持久层框架完成增、删、改、查原子性操作。实际就算是轻量级的对象,DAO没必要含有太复杂的其他对象,如果需要其他辅助对象为其服务:比如事务插入、日志操作记录。使用AOP面向他的切面进行拦截即可。Spring有整套方案,不做扩展。创建这些对象,在启动Web应用的时候实例化放到容器中即可,想要,容器自动为您注入。容器保证了对象的线程安全,所以这些对象是轻量级对象。
3. 重量级对象
那什么又是重量级对象呢,咱们用一个谁都能想到的例子,数据库连接java.sql.Connection。为何说Connection是一个重量级对象呢?我们在JDBC编程的时候仅仅使用了很少量的代码即完成了数据库的连接操作。一个Connection对象为我们操作数据库做了什么?
1):通过JDBC的驱动Driver屏蔽底层数据库网络协议,让我们不必关心具体的数据库通讯协议(Mysql有Mysql的协议、Oracle有Oracle的通讯协议)
2):通过数据库网络协议打开网络socket连接管道
3):根据建立的网络通道发送握手指令(所谓握手指令就是包含数据库用户名、数据库密码的二进制信息)
4):接收数据库端的握手结果信息再决定下面的通讯是否进行
关键是建立网络socket通道耗费资源着实不小。而且java.sql.Connection需要一直维持着这个网络通道。
相比于上面提到的DAO对象的创建,这个Connection对象创建的时候是不是确实显得历经沧桑。咱们举个例子,就像唐僧取经一样,李世民想要经书超度为他建功立业的亡魂,唐三藏就去了,历经千辛万苦取回来了,李世民让其诵念经文超度亡魂后发现这段时间那些死去的冤魂没再缠着他了,取回来的经文这个时候被李世民看经书占地方,下令烧掉了(垃圾回收器回收了)。过了一段时间又有亡魂开始缠着他了!怎么办?李世民说:“哦,御弟,麻烦你再去见佛祖一趟吧!”唐三藏之后又花了12年,再去西天见佛祖,取回了真经超度亡魂~~如果当时唐三藏说:“阿妹喂,陛下,当时您要是不下令烧掉,将经书交给我的大徒弟去管理,就不必这么麻烦~等我取回经书了,您也就快那什么啦”。
4. 对象池
对象池的概念和现实生活中的图书馆的管理极其相似。阅读这项看一本书,用读书卡去借一本书、看完了还回来,如果图书馆的书不够用了怎么办?那就麻烦图书采购小刘去市场买几本回来吧。这个本书太受欢迎了,原始的书的数量不够用啊。对象池就像是一个图书馆,图书管理员就像是对象调度器,借书人就像是调用对象的客户端。需要维护的就是图书馆和借书的记录凭证。这样看来资源需要维护图书馆和借书系统。但是这种维护在某种程度上来说是值得的。回到我们的编程世界中,Apache的common-pool组件就是一个开源的对象池工具,我们可以借助它的接口,就可以将重量级的对象做池化。
5. 环境搭建
首先从apache站点下载commons-pool组件包。将lib下面的jar包拷贝到项目classpath中。因为此实话组件还依赖于其他的apache的commos组件——commons-collections。所以还需要将此jar包加入到classpath。笔者搭建好的环境如下
/ApacheCommonPool/lib/commons-collections-2.1.1.jar
/ApacheCommonPool/lib/commons-pool-1.5.6-javadoc.jar
/ApacheCommonPool/lib/commons-pool-1.5.6-sources.jar
/ApacheCommonPool/lib/commons-pool-1.5.6.jar
简单的池化环境已经搭建完毕
6. 使用例程
在此历程中,我们测试一下Java常用对像,也是最通用的轻量级对象String的池化。再测试一下自定义的实体对象的池化。再次说明一点:String是绝对不适合做池化的,首先java.lang.String对象本身就不是什么重量级对象,初始化String对象也绝对不用经过什么西天取经的过程才能产生出来的,并且JVM已经对String做了池化处理。有一个String池维护已经创建好的字符串引用对象值。在此使用String仅仅是表示如何使用池化操作罢了。实际应用中,千万不要池化String对象。否则就有点得不偿失了。首先给出简单的POJO实体对象代码。
package key; public class Person { String id; String name; public Person() { } public Person(String id, String name) { this.id = id; this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "id:" + id + "---name:" + name; } }
这个用户POJO类很简单,就只有id和name属性。
下面是使用池工厂管理程序
/** * 池化工厂 * @author liuyan */ class KeyedPoolableObjectFactorySample extends BaseKeyedPoolableObjectFactory { /** * 创建对象方法 */ @SuppressWarnings("unchecked") public Object makeObject(Object clsName) throws Exception { if (clsName == null || !(clsName instanceof String) || "".equals(clsName)) { throw new RuntimeException("类名为空!"); } System.out.println("创建一个新的对象:" + clsName); Class cls = Class.forName((String) clsName); Object obj = cls.newInstance(); return obj; } @Override public void activateObject(Object key, Object obj) throws Exception { // TODO Auto-generated method stub super.activateObject(key, obj); System.out.println("激活对象"); } @Override public void destroyObject(Object key, Object obj) throws Exception { // TODO Auto-generated method stub super.destroyObject(key, obj); System.out.println("销毁对象"); } @Override public void passivateObject(Object key, Object obj) throws Exception { // TODO Auto-generated method stub super.passivateObject(key, obj); System.out.println("挂起对象"); } @Override public boolean validateObject(Object key, Object obj) { // TODO Auto-generated method stub System.out.println("验证对象"); return super.validateObject(key, obj); } }
池工厂对象就像是图书馆的调度管理员,需要创建新对象的时候就调用其makeObject()方法;其他的方法已经在程序中进行了说明。主要就是验证对象方法validateObject是验证是否已经存在了可复用的对象。在此历程中采用反射机制对目标对象进行实例化。
下面是使用程序
/** * 使用 * @author liuyan * */ public class KeyedObjectPoolSample { /** * @param args */ public static void main(String[] args) { Object obj = null; KeyedPoolableObjectFactory factory = new KeyedPoolableObjectFactorySample(); KeyedObjectPoolFactory poolFactory = new StackKeyedObjectPoolFactory( factory); KeyedObjectPool pool = poolFactory.createPool(); String key = null; try { key = "java.lang.String"; obj = pool.borrowObject(key); obj = "obj1"; // pool.returnObject(key, obj); obj = pool.borrowObject(key); pool.returnObject(key, obj); obj = pool.borrowObject(key); System.out.println(obj); System.out.println("============看另一个对象Person============="); key = "key.Person"; Person person1 = (Person) pool.borrowObject(key); person1.setId("1"); person1.setName("素还真"); System.out.println(person1); pool.returnObject(key, person1); System.out.println(person1); Person person2 = (Person) pool.borrowObject(key); person2.setId("2"); person2.setName("青阳子"); Person person3 = (Person) pool.borrowObject(key); person3.setId("3"); person3.setName("一页书"); Person person4 = (Person) pool.borrowObject(key); person4.setId("4"); person4.setName("业途灵"); System.out.println(person1); System.out.println(person2); System.out.println(person3); System.out.println(person4); pool.returnObject(key, person3); Person person5 = (Person) pool.borrowObject(key); System.out.println(person5); } catch (Exception e) { e.printStackTrace(); } finally { try { pool.close(); System.out.println(pool); } catch (Exception e) { e.printStackTrace(); } } } }
首先先建立一个字符串对象,引用值为 “obj1”。接着从对象池中借一个字符串对象出来obj指向这个借出来的对象,若池中有可复用的对象,直接给之,如果没有,调用makeObject()造一个新的对象出来给obj引用。用完后调用returnObject方法将对象还给池子。咱们再看下面使用Person对象,先从池中借一个Person对象person1。当然池子里面现在还没有任何Person对象。对池中对象赋值后,还给了池子。这个时候池子中就有一个被使用过的,并且属性已经发生改变的对象。下面person2变量向池子借了一个Person对象,此时池子里已经有了一个可复用的对象。那么不必调用makeObject方法,直接将已有的对象返回给客户端即可。然后对其赋值。把刚刚的1素还真改成了2青阳子,那么这个时候刚才的person1也是2青阳子,person1的引用指针没变,仅仅是引用的那块区域的字符串值发生了变化。之后还没等这个对象返还给池子呢,person3变量就向池子要对象,池子说:“等等,我给你make一个啊”,之后又调用了markObject方法创建了一个新的对象。这个新的对象就是3一页书。往下的4业途灵也是新的。当执行到
pool.returnObject(key, person3); Person person5 = (Person) pool.borrowObject(key); System.out.println(person5);
发现person5是刚刚归还的复用对象——3一页书。执行后控制台如下
创建一个新的对象:java.lang.String 激活对象 验证对象 创建一个新的对象:java.lang.String 激活对象 验证对象 验证对象 挂起对象 激活对象 验证对象 ~~~ ============看另一个对象Person============= 创建一个新的对象:key.Person 激活对象 验证对象 id:1---name:素还真 验证对象 挂起对象 id:1---name:素还真 激活对象 验证对象 创建一个新的对象:key.Person 激活对象 验证对象 创建一个新的对象:key.Person 激活对象 验证对象 id:2---name:青阳子 id:2---name:青阳子 id:3---name:一页书 id:4---name:业途灵 验证对象 挂起对象 激活对象 验证对象 id:3---name:一页书 org.apache.commons.pool.impl.StackKeyedObjectPool contains 0 distinct pools:
经过这个例子我们还应该清楚一个事实就是像这个可对局部变量访问(get)、赋值(set)的对象也不适合池化。因为别人用过了这样的对象,实际上留下了别人用过的痕迹。这样确实会造成局部变量用起来会不一致的线程安全问题。应该是对外仅仅提供服务的方法,并且不具备访问局部变量的对象,并且创建时十分消耗资源的对象才适合池化。到底是池化还是单例,这个当然没有绝对的答案,一切得看您的实际系统需要怎样做更合理。
发表评论
-
Web应用单点压力测试调优-第6季-阶段性总结
2014-03-14 12:24 3253阶段性总结 <! ... -
Web应用单点压力测试调优-第5季
2014-03-13 09:32 4017各项配置: my.cnf [clien ... -
Web应用单点压力测试调优-第4季
2014-03-12 14:55 3038调整5-Tomcat的启动JVM参数 首先先启动 ... -
单点网站压力测试调优-第3季
2014-03-11 16:21 3298调整2-调整配置,数据库连接池数量 mysql ... -
Web应用单点压力测试调优-第2季
2014-03-07 16:52 8751并发1000,准备时间1s,让它产生大量的等待请求 ... -
单点网站压力测试调优-第1季
2014-03-07 10:36 3829环境介绍 虚拟机配置 ... -
编程质量提高建议总结1(持续总结)
2014-03-05 19:42 1217编程质量提高建议总结1(持续总结) 1.混淆字母要明显 ... -
关于博客文章内容显示不全的问题
2011-06-14 09:36 2268关于博客文章内容显示不全的问题,我发现有些文章显示内容不全。 ... -
Maven3实战笔记05仓库依赖解析与插件解析
2011-06-07 09:00 33671. Maven仓库依赖解析机 ... -
将Sun的Open Message Queue与Spring集成
2011-05-06 09:01 34221. 前言 基于JMS标准的消息中间件实现的产品 ... -
要不要池化是个艰难的选择(转)-我觉得很生动就转载了下来
2011-05-05 09:50 1532转自http://www.ixpub.net/thre ... -
java.lang.IllegalStateException: STREAM错误的理解(转)
2011-05-04 18:09 13767转自http://dimple.iteye.com/blog/ ... -
Spring3配置声明式事务
2011-05-02 16:52 45021. 配置Spring3声明式事务 在Sprin ... -
Java基础复习笔记11基本排序算法
2011-04-25 13:20 20791. 排序 排序是一个历来都是很多算法家热衷的领 ... -
Java基础复习笔记08数据结构-二叉树和二叉树的遍历
2011-04-22 09:10 24711. 二叉树 一 ... -
Java基础复习笔记07数据结构-树的概述
2011-04-19 17:35 18531. 树的概念 如果线性表、栈、队列是线性结构( ... -
Java基础复习笔记06数据结构-队列
2011-04-19 17:25 16011. 队列 队列又是一种比较特殊的线性表,和栈一 ... -
Java基础复习笔记04数据结构-线性表
2011-04-15 14:14 22391. 线性表 线性表是数据结构的一种逻辑结构,其 ... -
Java基础复习笔记03面试、笔试、开发中我们不太注意的陷阱之流程控制、面向对象、异常处理
2011-04-13 09:59 21681. switch语句的用法 有人说:“笔者基础 ... -
Java基础复习笔记03面试、笔试、开发中我们不太注意的陷阱之多线程
2011-04-13 09:51 19151. 什么样的对 ...
相关推荐
Maven坐标:org.apache.commons:commons-pool2:2.10.0; 标签:apache、commons、pool2、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译...
开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发工具 commons-pool2-2.4.2开发...
commons-pool-1.3.jar+commons-pool.jar;java连接池jar包java连接池;java连接池jar;commons-pool-1.2.jar;commons-pool-1.3.jar+commons-pool.jar;java连接池jar包java连接池;java连接池jar;commons-pool-1.2.jar;...
Maven坐标:org.apache.commons:commons-pool2:2.0; 标签:apache、commons、pool2、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...
Maven坐标:org.apache.commons:commons-pool2:2.3; 标签:apache、pool2、commons、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...
Maven坐标:org.apache.commons:commons-pool2:2.4.3; 标签:apache、pool2、commons、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...
Maven坐标:org.apache.commons:commons-pool2:2.10.0; 标签:apache、pool2、commons、jar包、java、中英对照文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化...
对应Maven信息:groupId:org.apache.commons,artifactId:commons-pool2,version:2.5.0 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构...
commons-pool-1.1.jar, commons-pool-1.2.jar, commons-pool-1.3-src.jar, commons-pool-1.3.jar, commons-pool-1.4.jar, commons-pool-1.5.1.jar, commons-pool-1.5.2-sources.jar, commons-pool-1.5.2.jar, ...
DBCP(DataBase Connection Pool)是 apache common上的一个 java 连接池项目,也是 tomcat 使用的连接池组件,依赖 于Jakarta commons-pool 对象池机制,DBCP可以直接的在应用程序中使用。 使用DBCP会用到commons-...
commons-pool资源下载,东西齐全,包括api文档开发,Apache的对象池化工具commons-pool 当我们的应用中创建一个十分最重量级的对象的时候,往往为了节省资源成本,使用单例模式,整个的应用中就只有一个对象供大家...
commo-pool, commons-pool commons-pool commons-pool
commons-dbcp-1.2.2.jar和commons-pool-1.3.jar包,数据源包
commons-dbcp-1.4.jar和commons-pool-1.5.6.jar
Apache commons-pool本质上是"对象池",即通过一定的规则来维护对象集合的容器;commos-pool在很多场景中,用来实现"连接池"/"任务worker池"等,大家常用的dbcp数据库连接池,也是基于commons-pool实现.
赠送jar包:commons-pool-1.6.jar; 赠送原API文档:commons-pool-1.6-javadoc.jar; 赠送源代码:commons-pool-1.6-sources.jar; 赠送Maven依赖信息文件:commons-pool-1.6.pom; 包含翻译后的API文档:commons-...
Maven坐标:org.apache.commons:commons-pool2:2.9.0; 标签:apache、commons、pool2、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,...
DBCP (Database Connection Pool)是一个依赖 Jakarta commons-pool 对象池机制的数据库连接池,Tomcat 的数据源使用的就是 DBCP。
Maven坐标:org.apache.commons:commons-pool2:2.5.0; 标签:apache、pool2、commons、jar包、java、API文档、中文版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性...