`
zhang.jianjun
  • 浏览: 19527 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • NGG: 个人建议: 正确的做法应该是把样式放到外部css文件中,使用 ...
    js日期选择器

【JAVA优化编程】内存管理之——(6)对象重用与GC

阅读更多

6  对象重用与GC

    有时候我们为了提高系统的性能,避免重复耗时的操作,希望能够重用某些创建完成的对象,但是既然是重用(reuse)就涉及对象保存的问题,通常将用来缓存对象的应用称为对象池(ObjectPool),通过这个途径我们可以大大地提高应用的速度,减少内存需求,例如,我们经常提到的JDBC连接池与EJB实例池等概念都属于对象池的范畴。

    通过使用对象池的办法来提高系统性能,节约系统内存开销是一个非常简易、高效的方法,对象池通过对其所保存对象的共享与重用,缩减了应用线程反复重建、装载对象的过程所需要的时间,并且也有效地避免了频繁垃圾回收带来的巨大系统开销。

    下面我们给出对象池的代码框架,以帮助你理解对象池是怎样避免系统频繁的垃圾回收所带来的巨大系统开销的。下面是一个对象池的抽象类,也是应用对象池的基类:

public abstract class ObjectPool {
    private Hashtable locked, unlocked;
    private long expirationTime;

    abstract Object create();
    abstract void expire(Object o);
    abstract void validate(Object o);
    synchronized Object getObject() {...}
    synchronized void freeObject(Object o) {...}
}
 

 

    在这个类中声明了5个重要方法: 创建对象方法create()、对象过期方法expire()、获取对象方法getObject()、对象有效性验证方法validate()与对象释放方法freeObject()。我们可以通过create()方法创建新的对象实例,并且将这个对象实例保存到哈希表(Hashtable)对象中,当其他应用请求对象实例时,可以通过调用getObject()方法获取哈希表中的对象,并检测其有效性是否过期,如果一切正常则将该对象传递给调用者,调用者使用完对象实例后可以通过调用方法freeObject()将该对象实例释放(归还)给对象池。

    既然对象实例被保存,当应用试图重用该对象时就不需要重新创建新的对象,避免大量垃圾对象的产生,即使对象的生命周期较短可以被系统及时回收,但是这样会引发JVM频繁GC的危机导致系统性能下降。

    但是如果长时间地将对象保存在内存中,如果这些对象又不被经常使用无疑也会造成不必要的内存资源浪费,或者该对象在对象池中遭到破坏,如果不能将该对象及时清除而继续占用系统的内存资源,也是非常麻烦的。因此在应用对象池技术重用对象时应该考虑其必要性并权衡利弊做出最优的选择,如果决定使用对象池技术,需要采取相应的手段清除遭到破坏的对象,甚至在某些情况下需要清除对象池中所有的对象,并且为每个对象分配一个时间戳,设定对象的过期时间,当对象过期后及时将其在内存中清除,下面以JDBC连接池为例说明通过对象池技术重用对象中的技术要点,帮助你理解怎样才能更好地提高系统性能,降低系统内存的开销。

    在对象池中声明了对象创建方法abstract Object create() throws Exception。在JDBC连接池中也需要创建一个该抽象方法的实现方法Object create() throws SQLException,这个方法抛出了SQLException,在这个方法中通过对方法DriverManger.getConnection()的调用获取一个JDBC数据库连接对象。

Object create() throws SQLException {
    return ( DriverManger.getConnection(dsurl, usr, pwd) );
}
 

 

    JDBC数据库连接池在接收到外部请求获取连接对象的请求之后,要getConnection()方法中调用创建连接对象方法create()方法。调用create()方法的前提是,连接池要确认连接池中的连接对象数量。当连接池中的对象实例数没有达到对象池实例最大值,并且连接池中所有已存在的连接都处于被占用状态,也就是说,此时连接池中没有空闲连接对象。当具备了上述条件后,才可以通过调用create()方法,创建新的连接对象,响应外部获取连接的请求,然后将创建的对象传递给getObject()方法的调用者。为了同步多线程对资源的访问,getObject()方法的声明如下:

        synchronized Object checkOut() throws Exception

    在getConnection()方法处理过程中有可能抛出SQL异常,因此其声明如下:

public Connection getConnection() throws SQLException {
    try {
        return ( (Connection)super.getObject() );
    } catch (Exception ex) {
        throw ( (SQLException) ex );
    }
}
 

 

    为了防止已损坏连接对象残存在连接池中而不能被及时清除,浪费系统内存资源,可以通过一个专门的线程来清除这些连接对象,缩减系统内存开销。我们可以通过创建一个线程及时检测连接池中的对象是否有效,如果无效则主动清除,如下所示。

class ConnectionCleanUpThread extends Thread {
    private ObjectPool pool;
    private long sleepTime;

    ConncetionCleanUpThread (ObjectPool pool, long sleepTime) {
        this.pool = pool;
        this.sleepTime = sleepTime;
    }

    public void run() {
        while(true) {
            try {
                sleep(sleepTime);
           } catch (InterruptedException ex) {
                // 做相应处理
            }
            pool.cleanUp();
        }
    }
}
 

 

    通过这个线程,就可以完成上面所提到的无效连接对象的清除工作,这个线程是在ObjectPool类的构造器中被初始化并启动的。

... ...
public ObjectPool() {
    ...
    cleaner = new ConnectionCleanUpThread( this, expirationTime );
    cleaner.start();
    ...
}
... ...
 

 

    cleanUp()方法在清除所有无效Connection对象的同时,还会要求系统做垃圾回收工作,以及时回收这些被清除的对象。

synchronized void cleanUp() {
    Connection conn;
    long currentTime = System.currentTimeMillis();
    Enumeration enumeration = unlocked.keys();

    while (enumeration.hasMoreElements()) {
        conn = enumeration.nextElement();

        if ( (currentTime - ((long) unlocked.get(conn) ).longValue() ) > expirationTime ) {
            unlocked.remove( conn );
            expire( conn );
            conn = null; // 请注意这一行代码的作用
        }
    }
    System.gc();
}
 

 

    在这个方法中的最后一行代码强制系统做垃圾回收,这是因为我们已经将连接池中被清除的对象做了空值的赋值操作,也就是释放了对该对象的引用,使其对虚拟机来说变得不可达,转化为系统垃圾,然后回收之,释放其占用的内存,结合上面的知识很容易理解这一点。

    综上所述,使用对象池是有诸多好处的,但是我们一定要恰当地使用这项技术,否则反受其累。

    如果对象池中的对象过多,或者没有做必要的清除处理,没有考虑应用所运行环境的内存资源的限制等,都会使系统导致灾难性的错误。因此当你决定采用这种技术时应当依据上面我们讲解的知识,考虑周全。正如上面所说的,其他对象池的技术与连接池的技术都是类似的,因此我们讲解本节的目的就是想起到抛砖引玉的作用,使你在处理这方面的应用时不至于在内存管理方面出现可避免的疏漏。

0
0
分享到:
评论

相关推荐

    C语言接口与实现——创建可重用软件的技术

    与当前某些面向对象语言不同,C语言为创建可重用应用程 序接口(Application Programming Interface,API)提供的语言和功能支持非常少。尽管大多 数C语言程序员在自己所编写的每一个应用程序中都使用API和实现API的库...

    安卓Andriod源码——listview适配器优化重用.zip

    安卓Andriod源码——listview适配器优化重用.zip

    安卓Android源码——listview适配器优化重用.zip

    安卓Android源码——listview适配器优化重用.zip

    代码优化——cell重用

    对于从storyboard或xib启动的vc和view,即便是父类的storyboard或xib做了复杂的界面,子类也可以继承来复用父类的代码逻辑,同时把父类的storyboard或xib复制一份并改名为子类,在已有界面的基础上继续绘制新视图。...

    JAVA面向对象编程_孙卫琴2.pdf

    本章首先简要介绍了结构化的软件开发过程,然后介绍面向对象的软件开发过程,对...这个例子分别按照结构化开发方式和面向对象开发方式实现,从而鲜明地对比这两种开发方式对软件的可维护性、可扩展性和可重用性的影响。

    javascript面向对象编程

    JavaScript作为一门浏览器语言的核心思想;...如何实现JavaScript中缺失的面向对象特性,如对象的私有成员与私有方法;如何应用适当的编程模式,发挥JavaScript语言特有的优势;如何应用设计模式解决常见问题等。

    跟我学Java面向对象程序设计技术及应用——Java中的面向对象技术(第1部分).pdf

    (4)面向对象程序设计方法的编程优点:可重用性、可扩充性、可管理性。 2、面向对象程序设计方法与面向过程程序设计方法的对比 (1)从面向过程的代码中我们可以发现以下一些特点 1) 代码的顺序逻辑性较强 2) 当...

    GlideBitmapPool, Glide位图池是用于重用位图内存的内存管理库.zip

    GlideBitmapPool, Glide位图池是用于重用位图内存的内存管理库 Glide位图池 Bitmap位图池Glide位图池是用于重用位图内存的内存管理库。 因为它重用位图内存,所以不再反复调用 GC,因此运行流畅的应用程序。 它使用...

    JAVA编程实验:类的重用.doc

    JAVA编程实验:类的重用

    exceptional c++:47个c++工程难题、编程问题和解决方案(英文版)

    条款35:内存管理——之一 176 条款36:内存管理——之二 179 条款37:auto_ptr 186 7 误区、陷阱以及错误的惯用法 201 条款38:对象标识 201 条款39:自动转换 204 条款40:对象的生存期——之一 206 条款41...

    Java零基础-对象的创建和使用-内存分析.md

    内容概要: 本文档详细介绍了Java编程中对象的创建和使用,并对对象在内存中的分配和使用进行了详细分析。通过示例代码和详细解释,帮助读者理解对象的创建过程、内存分配和使用方法。 能学到什么: 理解对象的...

    Java是一种广泛使用的编程语言

    自动垃圾收集:Java提供了自动垃圾收集,这意味着开发人员不需要手动管理内存。当对象没有任何引用指向它们时,它们将被视为垃圾,然后由Java的垃圾收集器自动删除。 强类型:Java是强类型的编程语言,这意味着每个...

    Java培训教材Java编程技术复习纲要第四章类的重用共8

    Java培训教材Java编程技术复习纲要第四章类的重用共8页.pdf.zip

    Java性能优化

    要知道,当某个对象被定义为stataic的变量所引用,那么GC通常是不会回收这个对象所占有的内存,如 public class A{ static B b = new B();} 此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻...

    Java程序设计基础实训

    Java是面向对象的、支持多线程的解释型网络编程语言。它是目前Internet最流行的编程语言之一,具有高度的安全性、可移植性和代码可重用性。

    Java GUI编程.docx

    java中万事万物皆为对象,类和对象是java编程的核心。类可以看成是属性和行为的抽象、封装。必须先有概念才有实物,必须定义类才有对象,类是同一类型对象的模板。 面向对象语言,万事万物,皆为对象。面向对象思维...

    Java技术及其应用 02 面向对象结构(共106页).ppt

    Java是真正面向对象的编程语言 面向对象编程主要体现下列三个特性: ◇封装性 (Encapsulation) 它把所有的过程代码封装在类中,不再支持面向过程编程的方法。任何Java程序的框架就是类/接口的声明。 ◇继承 ...

    可重用代码管理器

    可重用代码管理器 增加代码复写率 提高编程效率

    优化AIX7内存性能

    优化 AIX 内存性能的基本步骤及重用命令,整理自IBM知识库。优化 AIX 内存性能的基本步骤及重用命令,整理自IBM知识库

    基于某JAVA地剪刀石头布游戏设计——Java课程设计报告材料-.doc

    目 录 前言3 1剪刀石头布游戏设计思路阐述4 2程序概要设计5 功能需求分析5 性能需求分析5 程序框图5 Java类与自定义类相互继承的层次关系6 Java类与自定义类的说明6 类中成员与作用7 2.5程序运行效果与存在的问题7 ...

Global site tag (gtag.js) - Google Analytics