`
zhang.jianjun
  • 浏览: 20217 次
  • 性别: 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
分享到:
评论

相关推荐

    Java之SSH深入浅出——精简剖析

    ### Java之SSH深入浅出——精简剖析:Struts框架详解 #### Struts框架起源与发展历程 Struts框架,作为Apache Jakarta项目的重要组成部分,自诞生之初便承载着推动JavaServer Pages(JSP)、Servlet、标签库及面向...

    《Java 工程师的编程逻辑》——用 java 看计算机世界

    Java的强类型系统和自动内存管理机制,如垃圾回收,为开发者提供了稳定和高效的编程环境。书中会详细解析这些概念,并通过实例演示如何在实际项目中应用。 面向对象设计(OOP)是Java编程的核心,书中将深入讨论...

    8.java学习第八章——面向对象.pdf

    Java 学习第八章——面向对象 #### 面向过程与面向对象的区别 在讨论面向过程和面向对象之前,我们先明确几个概念。编程语言根据其编程范式可以分为多种类型,其中面向过程和面向对象是最常见的两种。 **面向...

    Java面向对象编程思想.pdf

    Java 面向对象编程思想是 Java 编程语言的核心思想之一,通过封装、继承和多态三个特征,实现代码的重用和可维护性。 一、封装 封装是 Java 面向对象编程的三大特征之一,通过 Java 的类来实现数据和操作方法的...

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

    《C语言接口与实现——创建可重用软件的技术》是一本专注于C语言编程中库函数设计、实现以及高效使用的参考指南。本书为读者深入讲解了如何设计和实现可重用的软件模块,这些模块是构建大型、稳定应用的基石。本书...

    java基础优化编程

    可以通过在循环外部创建对象,并在循环内部复用,来优化内存使用。 #### 四、软引用与弱引用 软引用和弱引用是Java中用于实现缓存和内存管理的高级特性。软引用在内存不足时才回收,适合于实现缓存机制,如图片...

    面向对象编程思想小谈——类和对象.pdf

    面向对象编程(OOP)是一种编程范式,它使用“对象”来设计软件。对象可以包含数据,以字段的形式存在,通常被称为属性或特征;还可以包含代码,通常以方法的形式存在。对象内的方法可以访问和修改对象内的数据。 ...

    Thinking in Java 自学笔记——第一章 对象导论

    Thinking in Java 自学笔记——第一章 对象导论 本章节总结了面向对象程序设计(Object-oriented Programming, OOP)的基本概念和原则,以帮助读者更好地理解 Java 编程语言。以下是对标题、描述、标签和部分内容的...

    Java面向对象精髓编程

    "Java面向对象精髓编程"这个主题深入探讨了Java的核心特性——面向对象编程。面向对象编程(Object-Oriented Programming, OOP)是现代软件开发中的重要概念,它通过将数据和操作数据的方法封装在对象中,提高了代码...

    面向对象编程C++和Java比较教程 中英文完整版 pdf

    Java的语法与C++类似,但它更加强调安全性、可移植性和自动内存管理。Java使用垃圾回收机制来自动释放不再使用的对象,避免了C++中的内存泄漏问题。Java也支持接口,这使得实现多继承成为可能,而C++只支持单继承。 ...

    java代码优化编程

    【Java代码优化编程】 在Java编程中,代码优化是一个关键环节,目的是使程序在有限的资源下更高效地运行。优化主要包括两个方面:减小代码体积和提高代码执行效率。以下是一些关于如何提高Java代码效率的具体策略:...

    面向对象的编程——Java教案 (jaca 库、java的软件开发技术、附带实例java 的应用程序 电子书文本形式)

    面向对象的编程是一种重要的软件开发方法,...总之,"面向对象的编程——Java教案"提供了全面的学习资源,涵盖了Java面向对象编程的基础和进阶内容,配合具体的代码示例,有助于提升学习者在Java开发领域的技能和经验。

    精通JAVA——JDK(高清PDF文件)

    4. **JVM内部机制**:了解Java虚拟机(JVM)的工作原理,包括类加载、内存管理、垃圾回收以及性能优化策略,这有助于编写出更加高效和稳定的代码。 5. **Java开发工具**:讲解JDK自带的工具,如javac编译器、...

    JAVA核心知识点整理——java自学资料.rar

    Java是世界上最流行的编程语言之一,尤其在企业级应用开发领域占据主导地位。这份"JAVA核心知识点整理——java自学资料.rar"包含了一份详细的Java学习资源,旨在帮助已经具备一定Java基础知识的开发者进一步提升技能...

    Visual C++编程技巧典型案例解析——基础与应用篇(下)

    《Visual C++编程技巧典型案例解析——基础与应用篇(下)》是一本深入探讨Visual C++编程技术的专著,其主要目标是帮助开发者提升在实际项目中的编程技能和问题解决能力。书中涵盖了大量的实例源代码,使得学习者...

    提升LabVIEW程序性能——优化内存管理PPT教案.pptx

    通过优化内存管理,可以显著提高 LabVIEW 程序的运行效率和可靠性。本文将详细介绍 LabVIEW 程序内存管理的重要性、监测 VI 内存占用和运行时间的工具、优化 LabVIEW 程序内存管理的基础篇和高级篇。 Importance ...

    java高效编程.pdf

    9. **对象创建与内存管理**: - 避免一次性创建大量对象,特别是大对象,这可能导致垃圾收集器(GC)频繁工作。 - 显示声明数组大小,并根据需求合理分配空间。 10. **SQL注入攻击**: - SQL注入是一种常见的...

    面向对象编程C++和Java比较教程

    Java的核心特性同样包括面向对象、封装、继承和多态,但它的语法更加简洁,自动内存管理(垃圾回收)减轻了程序员的工作负担,同时Java拥有丰富的类库,尤其在网络编程和企业应用开发中占据主导地位。 C++与Java在...

Global site tag (gtag.js) - Google Analytics