使用Jakarta Commons Pool处理对象池化
简介:?恰当地使用对象池化技术,可以有效地减少对象生成和初始化时的消耗,提高系统的运行效率。Jakarta Commons Pool组件提供了一整套用于实现对象池化的框架,以及若干种各具特色的对象池实现,可以有效地减少处理对象池化时的工作量,为其它重要的工作留下更多的精力和时间。
<!--<p alt="应用Jakarta Commons Pool处理对象池化" width="20" height="20" style="max-width: 100%;height: auto;width: auto\9;" src="//img.reader8.net/uploadfile/jiaocheng/20140140/2739/2014012717395411522.gif">?
<!-- dW_Summary_Area_END --><!-- CONTENT_BODY --><!-- MAIN_COLUMN_BEGIN --><!-- Related_Searches_Area_And_Overlays_Begin --><!-- MAIN_COLUMN_CONTAINER_BEGIN -->为这个类添加一个void activateObject(Object obj)方法。这个方法用于将对象“激活”——设置为适合开始使用的状态。为这个类添加一个void passivateObject(Object obj)方法。这个方法用于将对象“挂起”——设置为适合开始休眠的状态。为这个类添加一个boolean validateObject(Object obj)方法。这个方法用于校验一个具体的对象是否仍然有效,已失效的对象会被自动交给destroyObject方法销毁为这个类添加一个void destroyObject(Object obj)方法。这个方法用于销毁被validateObject判定为已失效的对象。最后完成的PoolableObjectFactory类似这个样子:
另外,ObjectPool接口还定义了几个可以由具体的实现决定要不要支持的操作,包括:
void clear()
清除所有当前在此对象池中休眠的对象。
int getNumActive()
返回已经从此对象池中借出的对象的总数。
int getNumIdle()
返回当前在此对象池中休眠的对象的数目。
void setFactory(PoolableObjectFactory factory)
将当前对象池与参数中给定的PoolableObjectFactory相关联。如果在当前状态下,无法完成这一操作,会有一个IllegalStateException异常抛出。
Pool组件自带的KeyedObjectPool的实现有StackKeyedObjectPool和GenericKeyedObjectPool两种。它们的使用方法分别与它们各自的近亲KeyedObjectPool和KeyedObjectPool基本一致,只是原来使用GenericObjectPool.Config的地方要使用GenericKeyedObjectPool.Config代替。
要避免这种情况,就要进一步采取一些措施才行:
基本上,可以说Pool组件是线程相容的。但是要在多线程环境中使用,还需要作一些特别的处理。
回页首
什么时候不要池化
采用对象池化的本意,是要通过减少对象生成的次数,减少花在对象初始化上面的开销,从而提高整体的性能。然而池化处理本身也要付出代价,因此,并非任何情况下都适合采用对象池化。
Dr. Cliff Click在JavaOne 2003上发表的《Performance Myths Exposed》中,给出了一组其它条件都相同时,使用与不使用对象池化技术的实际性能的比较结果。他的实测结果表明:
对于类似Point这样的轻量级对象,进行池化处理后,性能反而下降,因此不宜池化; 对于类似Hashtable这样的中量级对象,进行池化处理后,性能基本不变,一般不必池化(池化会使代码变复杂,增大维护的难度); 对于类似JPanel这样的重量级对象,进行池化处理后,性能有所上升,可以考虑池化。根据使用方法的不同,实际的情况可能与这一测量结果略有出入。在配置较高的机器和技术较强的虚拟机上,不宜池化的对象的范围可能会更大。不过,对于像网络和数据库连接这类重量级的对象来说,目前还是有池化的必要。
基本上,只在重复生成某种对象的操作成为影响性能的关键因素的时候,才适合进行对象池化。如果进行池化所能带来的性能提高并不重要的话,还是不采用对象池化技术,以保持代码的简明,而使用更好的硬件和更棒的虚拟机来提高性能为佳。
回页首
结束语
恰当地使用对象池化,可以有效地降低频繁生成某些对象所造成的开销,从而提高整体的性能。而借助Jakarta Commons Pool组件,可以有效地减少花在处理对象池化上的工作量,进而,向其它重要的工作里,投入更多的时间和精力。
<!-- CMA ID: 53399 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->参考资料
很多疑难问题的答案都可以通过查阅Pool组件的Javadoc文档和源代码的方法解决。从 Pool组件的官方站点 上,还可以进一步得到许多有用的信息。
DBCP 是一个基于Pool组件的Java数据库连接池管理组件,同时也可以作为Pool组件的用法示例使用。
蔡学镛在 《Java夜未眠(Sleepless Java)》中的 《测不准原理》一文里,介绍了Java中的包括“软引用”(Soft Reference)在内的各种不同的引用的特点和用处。
Martin Fowler在 《Refactoring -- Improving the Design of Existing Code》(中译本名为 《重构——改善既有代码的设计》,由侯捷、熊节合译)一书的第三章《代码的坏味道(Bad Smells in Code)》中讨论了被称为“Long Parameter List”和“Data Class”的“坏味道”。并指明了一些可以用于对付这些问题的重构手法。
Brian Goetz在IBM developerWorks上发表的 《Java 理论与实践:描绘线程安全性》一文中,说明了为什么单纯地使用同步方法还不能让对象就此在多线程环境里高枕无忧的原因。
Dr. Cliff Click发表在JavaOne 2003上的 《Performance Myths Exposed》(Session #1522),给出了一组包括“对象池化”在内的、对“能提高Java程序性能”的做法的实际效果的测试数据,和一些恰当使用这些做法的建议。
关于作者
孙海涛从1994年6月的一个风雨交加的下午开始了他的编程生涯。目前,他的兴趣集中于Java、Web、开源软件和人机交互。但是,这并不表示他不会对其它的事物给予足够的关心和重视。可以通过 alexhsun@hotmail.com与他取得联系。
?
?
http://www.ibm.com/developerworks/cn/java/l-common-pool/